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のファイルをコピーする場合、「コピーしたばかりの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

通常、1 回の読み取り/書き込みサイクルでファイル全体をコピーしようとはしません。これにより、(特に) メモリ割り当てが失敗する可能性がかなり高くなり、仮想メモリの割り当て/使用が終了した場合に非常に非効率になります。

代わりに、通常は適切なサイズ (たとえば、1 メガバイトまたは 2 メガバイト) のバッファーを割り当ててから、次のようにループでコピーを行います。

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 に何かを書き込もうとすると、プログラムで許可されていないため、スタックオーバーフローが発生します。

于 2012-06-15T17:06:53.170 に答える