2015-03-16 2 views
1

Я пытаюсь скопировать файлы с помощью этой функции, но выходные файлы содержат странные символы.Функция копирования файла в C

int File_Copy (char FileSource [], char FileDestination []) 
{ 
    int  result  = -1; 
    char c [1]; 
    FILE *stream_R = fopen (FileSource,  "r"); 
    FILE *stream_W = fopen (FileDestination, "w"); //create and write to file 

    while ((c [0] = (char) fgetc(stream_R)) != EOF) 
    { 
     fprintf (stream_W, c); 
    } 

    //close streams 
    fclose (stream_R); 
    fclose (stream_W); 

    return result; 
} 

Я не знаю, что не так. Пожалуйста помоги.

+0

[ 'fgetc()'] (HTTP: // port70. net/~ nsz/c/c11/n1570.html # 7.21.7.1) возвращает значение типа 'int'. Преобразование его в 'char' теряет информацию. – pmg

ответ

4

Проблема заключается в том, что c[1] не будет работать как строка, поскольку она не может содержать завершающего nul байт, поэтому он должен быть

char c[2] = {0}; 

, а также c[2] должны быть int, как это

int c[2] = {0}; 

потому что fgetc() возвращает int, поэтому ваш код потенциально переполнен c[0], но у вас также есть некоторые другие вещи, которые вы можете улучшить.

  1. Вам не нужно c быть массив, можно просто объявить его как это.

    int c; 
    

    , а затем использовать fputc(); вместо fprintf().

  2. Вы должны проверить, что ни один из вызовов fopen() не удался, иначе ваша программа вызовет неопределенное поведение из-за разыменования указателя NULL.

Это надежная версия вашей собственной программы с проблемой вы описали в своем вопросе фиксированной

/* ** Function return value meaning 
* -1 cannot open source file 
* -2 cannot open destination file 
* 0 Success 
*/ 
int File_Copy (char FileSource [], char FileDestination []) 
{ 
    int c; 
    FILE *stream_R; 
    FILE *stream_W; 

    stream_R = fopen (FileSource, "r"); 
    if (stream_R == NULL) 
     return -1; 
    stream_W = fopen (FileDestination, "w"); //create and write to file 
    if (stream_W == NULL) 
    { 
     fclose (stream_R); 
     return -2; 
    }  
    while ((c = fgetc(stream_R)) != EOF) 
     fputc (c, stream_W); 
    fclose (stream_R); 
    fclose (stream_W); 

    return 0; 
} 
+0

У меня было это как int изначально. однако fprintf() принимает тип constchar [], как в -> int fprintf (поток FILE *, const char formatString [], ...). С этим я получил FATAL RUN-TIME ERROR. что я могу сделать? – CaTx

+0

@CaTx, но вам не нужно 'fprintf()' писать один символ. –

+0

что я должен использовать вместо этого? – CaTx

2

Есть ли причина, почему вы пытаетесь скопировать файл на один байт в то время? Это будет так медленно! Хотя основная проблема заключается в том, что вы используете fprintf(), а функции printf() предназначены для печати форматированных строк, а не для отдельных символов.

Если вы просто толкая байты вокруг из одного файла в другой, то вы должны использовать Fread и FWRITE вместо этого, например, так:

int File_Copy(char FileSource[], char FileDestination[]) 
{ 
    char c[4096]; // or any other constant you like 
    FILE *stream_R = fopen(FileSource, "r"); 
    FILE *stream_W = fopen(FileDestination, "w"); //create and write to file 

    while (!feof(stream_R)) { 
     size_t bytes = fread(c, 1, sizeof(c), stream_R); 
     if (bytes) { 
      fwrite(c, 1, bytes, stream_W); 
     } 
    } 

    //close streams 
    fclose(stream_R); 
    fclose(stream_W); 

    return 0; 
} 
+0

Я не знал о других функциях. ваш путь, похоже, имеет ограничение на размер файла (размер c []). есть ли способ изменить его, чтобы удалить ограничение? – CaTx

+0

Эта версия быстрее, потому что она считывает 4096 байт за раз. Если вы хотите читать по 1 байт за один раз, измените значение 4096 на 1. Также необходимо обработать ошибки ввода-вывода, например, в ответ iharob. –

+0

@CaTx Нет ограничений на размер файла. Код копирует 4096 байт за раз, в цикле, пока все данные не будут скопированы. Это несколько быстрее, чем копирование байта за раз, за ​​счет немного большего использования памяти (но что такое 4 КБ в эти дни?) – Enno

Смежные вопросы