#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));
}
答案 0 :(得分:4)
通常,不想要尝试在单个读/写周期中复制整个文件。这有(除其他外)你的内存分配失败的相当大的机会,或者如果你最终分配/使用一些虚拟内存,效率非常低。
相反,您通常希望分配一个合理大小的缓冲区(例如,一兆字节或两兆字节),然后在循环中进行复制,例如:
char *buffer = malloc(1024 * 1024);
while ((bytes=fread(buffer, 1, sizeof(buffer), infile)) > 0)
fwrite(buffer, 1, bytes, outfile);
当然,您也可以检查fwrite
的返回值,并且(例如)如果没有写入您请求的金额,则退出循环。例如,如果您正在移动文件而不是仅复制文件,这一点尤其重要 - 您只需要在/确定副本成功时删除原始文件。
答案 1 :(得分:1)
如果fread / fwrite没有复制您期望的字符数,则调用ferror()来检查I / O流的错误状态
答案 2 :(得分:1)
根据你发布的代码,我认为你在这一行上犯了一个错误。
fwrite(buffer, 1, file_size, file_to_copy);
你试图在file_to_copy中写入一些已经关闭的东西,这是程序不允许的,所以它会给你一个stackoverflow。