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

int main(int argc, char *argv[]){

  if(argc != 3){
    printf("Usage: ./copy filename newfile\n");
    exit(1);
  }

  int bytes;
  long file_size, file_copied_size;
  FILE *file_to_copy, *new_file;

  if((file_to_copy = fopen(argv[1], "rb")) == NULL){
    printf("File cannot be opened - read\n");
    exit(1);
  }
  if((new_file = fopen(argv[2], "wb")) == NULL){
    printf("File cannot be opened - write\n");
    exit(1);
  }

  fseek(file_to_copy, 0, SEEK_END);
  file_size = ftell(file_to_copy);
  rewind(file_to_copy);

  char *buffer = malloc(1024 * 1024); /* Imposto un buffer di 1MB per maggiore efficienza */ 
  if(!buffer){
    printf("Errore allocazione memoria\n");
    fclose(file_to_copy);
    fclose(new_file);
    exit(1);
  }

   /* In questo modo copio file grandi 1MB alla volta così il trasferimento è più veloce ed efficiente inoltre fread() ritorna 0 quando c'è un errore o quando incontra EOF */
  //while ((bytes=fread(buffer, 1, sizeof(buffer), file_to_copy)) > 0){
  while (!feof(file_to_copy)){
    bytes = fread(buffer, 1, sizeof(buffer), file_to_copy);
    fwrite(buffer, 1, bytes, new_file);
    if(ferror(new_file)){
      perror("Errore scrittura"); /* perror printa anche l'errore che ferror ha incontrato */
      fclose(file_to_copy);
      fclose(new_file);
      exit(1);
    }
  }

  fseek(new_file, 0, SEEK_END);
  file_copied_size = ftell(new_file);
  rewind(new_file);
  if(file_size != file_copied_size){
    printf("Il file %s non è stato copiato correttamente\n", argv[2]);
  }
  else{
    printf("File successfully copied :)\n");
  }  
  fclose(file_to_copy);
  fclose(new_file);
  free(buffer);

  return EXIT_SUCCESS;
}

编辑:我已经更新了代码
我有一些疑问:
1)我必须检查 fread 的返回码,因为 - 例如 - 如果字节由于错误而变为 0,0 将被写入复制的文件中。
但我的问题是:怎么做?因为 fread可以返回 0 但也可以返回一个短值....
2)如何读取文件?如果我复制一个 5MB 的文件,fread 怎么能在 1MB 中从 1MB 移动而没有说“嘿,你必须在刚刚复制的 1MB 之后将偏移量 1MB”?
3)为什么不每次使用后清除缓冲区?我的意思是:

while (!feof(file_to_copy)){
        bytes = fread(buffer, 1, sizeof(buffer), file_to_copy);
        fwrite(buffer, 1, bytes, new_file);
        memset(buffer, 0, sizeof(buffer));
}
4

3 回答 3

4

通常,您不想尝试在单个读/写周期中复制整个文件。这(除其他外)很有可能导致您的内存分配失败,或者如果您最终分配/使用一些虚拟内存,则效率极低。

相反,您通常希望分配一个合理大小的缓冲区(例如,一兆或两兆字节),然后在循环中进行复制,例如:

char *buffer = malloc(1024 * 1024);  

while ((bytes=fread(buffer, 1, 1024 * 1024, infile)) > 0)
    fwrite(buffer, 1, bytes, outfile);

当然,您也可以检查返回值fwrite并(例如)退出循环,如果它没有写入您请求的数量。例如,如果您正在移动文件而不是仅仅复制它,这一点尤其重要——您只想在/如果您确定复制成功时删除原始文件。

于 2012-06-15T16:43:20.447 回答
1

如果 fread/fwrite 没有复制您期望的字符数,您调用ferror()来检查 I/O 流的错误状态

于 2012-06-15T16:56:20.490 回答
1

根据您发布的代码,我认为您在这一行犯了一个错误。

fwrite(buffer, 1, file_size, file_to_copy);

您尝试将某些内容写入已经关闭的 file_to_copy 中,这是程序不允许的,因此它为您提供了 stackoverflow。

于 2012-06-15T17:06:53.170 回答