2013-04-10 4 views
1

Я хочу, чтобы прочитать текстовый файл и передать его содержимое в другой текстовый файл в C, Вот мой код:копирование содержимого текстового файла в C

   char buffer[100]; 

      FILE* rfile=fopen ("myfile.txt","r+"); 
      if(rfile==NULL) 
      { 
       printf("couldn't open File...\n"); 
      } 


      fseek(rfile, 0, SEEK_END); 
      size_t file_size = ftell(rfile); 
      printf("%d\n",file_size); 
      fseek(rfile,0,SEEK_SET); 
      fread(buffer,file_size,1,rfile); 


      FILE* pFile = fopen ("newfile.txt" , "w+"); 
      fwrite (buffer , 1 ,sizeof(buffer) , pFile); 
      fclose(rfile); 
      fclose (pFile); 
      return 0; 
      } 

проблема, с которой я столкнулся это внешний вид в ненужных данных в принимающем файле, Я попробовал функцию fwrite с «sizeof (buffer)» и «file_size». В первом случае он отображает большее количество бесполезных символов, а во втором случае количество бесполезных символов только 3, я был бы очень признателен, если бы кто-то указал мою ошибку и сказал мне, как избавиться от этих бесполезных персонажей ...

+0

Большинство файлов размером более 100 байт. Поэтому вам нужно прочитать файл в кусках, чтобы избежать переполнения буфера. Я бы использовал более большой размер буфера (например, 4096 или даже 65536 байт) и повторил это. Другой совет в ответах о том, как обратить внимание на порядок аргументов на 'fread()' и возвращаемое значение, также верен. –

ответ

2

Вам необходимо проверить возвращаемые значения от всех вызовов до fseek(), fread() и fwrite(), даже fclose().

В вашем примере у вас есть fread() 1 блок длиной 100 байт. Часто лучше изменить параметры, например: ret = fread(buffer,1,file_size,rfile). Значение ret покажет, сколько байтов он может прочитать, вместо того, чтобы просто сказать, что он не может прочитать полный блок.

+0

@hyde, справедливо. –

+0

@ AmigableClarkKant, вы прямо сейчас возвращаете мне 29 байт ... –

+0

@AaymanKhalid, отлично. Затем вы можете создать цикл вокруг своих чтений и записей, который сохраняет чтение и запись до тех пор, пока не будет установлен параметр 'feof (rfile)'. (Или до тех пор, пока вы не прочитаете байты file_size, если вы доверяете файлу не изменять.) Если вы используете 'feof (rfile)', вам не нужно знать, насколько велик файл в целом, ваш цикл будет копироваться до конец файла. (Это может даже избежать неприятностей с очень большими файлами, но это еще одна история ...) –

3

В тексте принимаете все содержимое buffer (100 символов). Вам нужно написать точное количество прочитанных данных.

fwrite(buffer, 1, file_size, pFile) 

Добавление большего количества проверок для кода:

#include <stdio.h> 
#include <stdlib.h> 

#define BUFFER_SIZE 100 

int main(void) { 
    char buffer[BUFFER_SIZE]; 
    size_t file_size; 
    size_t ret; 

    FILE* rfile = fopen("input.txt","r+"); 
    if(rfile==NULL) 
    { 
     printf("couldn't open File \n"); 
     return 0; 
    } 

    fseek(rfile, 0, SEEK_END); 
    file_size = ftell(rfile); 
    fseek(rfile,0,SEEK_SET); 

    printf("File size: %d\n",file_size); 

    if(!file_size) { 
     printf("Warring! Empty input file!\n"); 
    } else if(file_size >= BUFFER_SIZE){ 
     printf("Warring! File size greater than %d. File will be truncated!\n", BUFFER_SIZE); 
     file_size = BUFFER_SIZE; 
    } 

    ret = fread(buffer, sizeof(char), file_size, rfile); 
    if(file_size != ret) { 
     printf("I/O error\n"); 
    } else { 
     FILE* pFile = fopen ("newfile.txt" , "w+"); 
     if(!pFile) { 
      printf("Can not create the destination file\n"); 
     } else { 
      ret = fwrite (buffer , 1 ,file_size , pFile); 
      if(ret != file_size) { 
       printf("Writing error!"); 
      } 
      fclose (pFile); 
     } 
    } 
    fclose(rfile); 
    return 0; 
} 
+1

yes Я пробовал с file_size, но он уменьшает количество бесполезных символов, не устраняет их ... @ Bechir –

+1

@AaymanKhalid, что может быть связано с тем, что fread() не читал все. Проверьте его возвращаемое значение. –

+0

@ AmigableClarkKant, я проверил значение fread и действительно «zero» :( –

0

Примечание ftell возвращает long, не size_t. Впрочем, здесь неважно. Однако ftell не обязательно является байтовым смещением. Стандарт требует, чтобы это было приемлемым аргументом для fseek. Вы можете получить лучший результат от fgetpos, но он имеет такую ​​же проблему переносимости из-за отсутствия спецификации по стандарту. (Исповедь: я не проверял сам стандарт, получил все это из manpages.)

Более надежный способ получить размер файла - fstat.

#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd> 

struct stat stat_buf; 
if (fstat(filename, &buf) == -1) 
    perror(filename), exit(EXIT_FAILURE); 
file_size = statbuf.st_size; 
0

Я думаю, что параметры, которые вы передали в fwrite, не в правильной последовательности.

Для меня это должно быть, как что-

FWRITE (буфер, размер, 1, Pfile)

как синтаксис FWRITE является size_t FWRITE (сопзЬ пустота * PTR, size_t размера, size_t nmemb , Поток FILE *);

Функция fwrite() записывает элементы данных nmemb, каждый размер байта длиной, в поток, на который указывает поток, получая их из местоположения, заданного параметром ptr.

Итак, измените последовательность и повторите попытку.

1

Вот реализация (почти) общего назначения функции копирования файлов:

void fcopy(FILE *f_src, FILE *f_dst) 
{ 
    char   buffer[BUFSIZ]; 
    size_t   n; 

    while ((n = fread(buffer, sizeof(char), sizeof(buffer), f_src)) > 0) 
    { 
     if (fwrite(buffer, sizeof(char), n, f_dst) != n) 
      err_syserr("write failed\n"); 
    } 
} 

Учитывая поток открыт файл f_src для чтения и другой открытый файл потока f_dst писать, он копирует (оставшуюся часть) файл, связанный с f_src файлу, связанному с f_dst. Он делает это умеренно экономично, используя размер буфера BUFSIZ от <stdio.h>. Часто вы обнаружите, что большие буферы (например, 4 KiB или 4096 байт, даже 64 KiB или 65536 байт) будут давать лучшую производительность. Большее преимущество в 64 KiB дает много, но YMMV.

Приведенный выше код вызывает функцию сообщения об ошибке (err_syserr()), которая, как предполагается, не возвращается. Вот почему я назвал это «почти общей целью». Функция может быть повышен вернуть int значение, 0 в случае успеха и EOF на провал:

enum { BUFFER_SIZE = 4096 }; 

int fcopy(FILE *f_src, FILE *f_dst) 
{ 
    char   buffer[BUFFER_SIZE]; 
    size_t   n; 

    while ((n = fread(buffer, sizeof(char), sizeof(buffer), f_src)) > 0) 
    { 
     if (fwrite(buffer, sizeof(char), n, f_dst) != n) 
      return EOF; // Optionally report write failure 
    } 
    if (ferror(f_src) || ferror(f_dst)) 
     return EOF; // Optionally report I/O error detected 
    return 0; 
} 

Обратите внимание, что этот проект не открывается или закрыть файлы; он работает с открытыми файловыми потоками. Вы можете написать оболочку, которая открывает файлы и вызывает функцию копирования (или включает в себя код копирования в функцию). Также обратите внимание, что для изменения размера буфера я просто изменил определение буфера; Я не изменил основной код копирования. Также обратите внимание, что любая «служебная нагрузка функции» при вызове этой маленькой функции полностью заполнена издержками самих операций ввода-вывода.

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