2016-01-31 3 views
-1

Я написал следующий код для копирования одного файла в другой. Хотя код работает, код по-прежнему печатает оба сообщения об ошибках. Почему это ? Я полный новичок в программировании Unix и C (хотя раньше я работал с C++), поэтому любая помощь в максимально возможной степени была бы замечательной. Благодаря !Копирование одного файла в другой (Unix/C)?

int main(int argc, char *argv[]) 
{ 
    int n; 
    char buf[4096]; 
    while ((n=read(open(argv[1], O_RDONLY) , buf, 4096))>0) 
    { 
     if (write(creat(argv[2], S_IREAD | S_IWRITE), buf, n)!=n) 
      printf("Error writing to file.\n"); 
    } 
    if (n<0) 
     printf("Error reading from file.\n"); 
    exit(0); 
} 
+1

Вы повторно открыть и файлы с каждой итерации цикла. –

+0

* «Код работает» *, но действительно ли вы проверяли, что целевой файл имеет тот же контент, что и исходный файл? Пожалуйста, проверьте размер файла> 4096. –

+0

Что вы думаете, где начинается чтение вновь открытого файла? И что делает 'creat'e fucntion, если файл уже существует? – Olaf

ответ

3

Вы открываете файл в каждой итерации и попытке creat файл в каждой итерации.

Так что, за исключением самой первой итерации, все последующие записи не сработают. Вероятно, это «похоже, работает», потому что ваш входной файл содержит менее 4096 байт. Поэтому первым призывом писать было сделать так, чтобы все было скопировано. Если вы используете вход с более чем 4096 байтами, вы увидите только первые 4096 байт (при условии, что оба read() и write() не сбой).

Если write() бы удалось все время (например, вы имели creat() вне цикла), то open() вызов непрерывно открывает тот же файл, и потенциально бесконечный цикл или ваша система будет работать из дескриптора файла и возвращает недействительный файловый дескриптор и read() не удастся.

Короче говоря: не писать код как то :)

Move оба вызова к open() и creat() вне цикла:

int fd = open(argv[1], O_RDONLY); 
if (fd == -1) { 
    perror("open"); 
    exit(1); 
} 

int fd2 = creat(argv[2], S_IREAD | S_IWRITE); 
if (fd2 == -1) { 
    perror("write"); 
    exit(1); 
} 

while ((n=read(fd , buf, 4096)) > 0) 
{ 
    if (write(fd2 , buf, n) != n) 
     printf("Error writing to file.\n"); 
} 
+0

Также добавьте некоторую проверку ошибок. Убедитесь, что fd (дескрипторы файлов) не являются отрицательными. Пути файлов через командную строку могут быть недействительными. – BryanT

+0

Добавлена ​​проверка ошибок. Благодарю. –

2

выше ответ пятнистый на один, однако следует воздержитесь от использования creat(), поскольку create() является устаревшей функцией. create (имя файла, режим); эквивалентно open (имя файла, O_WRONLY | O_CREAT | O_TRUNC, режим);

http://www.gnu.org/software/libc/manual/html_node/Opening-and-Closing-Files.html

Код может быть лучше записать в виде:

#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <sys/stat.h> 

#define BUFSIZE 4096 

int main(int argc, char **argv) 
{ 
    int infd, outfd; 
    int n; 
    char *infile = NULL; 
    char *outfile = NULL; 
    int src_flags, dest_flags; 
    mode_t dest_perms; 
    char buf[BUFSIZE]; 

    if (argc < 3) { 
     fprintf(stderr, "At least src and dest files must be specified\n"); /*Never rely on users' inputs*/ 
     /*Print usage information if possible*/ 
     exit(EXIT_FAILURE); 
    } 

    infile = argv[1]; 
    outfile = argv[2]; /*Presuming the order*/    

    src_flags = O_RDONLY; 
    dest_flags = O_CREAT | O_WRONLY | O_TRUNC; 
    /*creat() is equivalent to open(fname, O_CREAT | O_WRONLY | O_TRUNC, mode)*/ 
    dest_perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /*rw-rw-rw-*/ 

    infd = open(infile, src_flags); 
    if (infd == -1) { 
     perror("cannot open src "); 
     exit(EXIT_FAILURE); 
    } 

    outfd = open(outfile, dest_flags, dest_perms); 
    if (outfd == -1) { 
     perror("cannot open dest "); 
     exit(EXIT_FAILURE); 
    } 

    while ((n = read(infd, buf, BUFSIZE)) > 0) { 
     if (write(outfd, buf, n) != n) { 
      fprintf(stderr, "failed to write buf\n"); 
      goto exit_failure; 
     } 
    } 

    if (n == -1) { 
     fprintf(stderr, "read() failed\n"); 
     goto exit_failure; 
    } 

exit_failure: 
    if (infd) { 
     close(infd); 
    } 

    if (outfd) { 
     close(outfd); 
    } 

    printf("Copy successful\n"); 

    exit(EXIT_SUCCESS); 
} 
Смежные вопросы