问题
#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;
}
EDIT: i've updated the code
I have some doubts:
1) I have to check the return code of fread because - for example - if bytes become 0 due to an error, 0 will be written into the copied file.
But my question is: how to do it? Because fread can return 0 but can also return a short value ....
2) how can read go throught the file? If i copy a 5MB file how can fread move from 1MB in 1MB without something that say to it "hey you have to put your offset 1MB after the 1MB you've just copied"?
3) why not to clear the buffer after every use? I mean something like:
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));
}
回答1:
Usually, you don't want to try to copy an entire file in a single read/write cycle. This has (among other things) a fairly substantial chance of your memory allocation failing, or being horribly inefficient if you end up allocating/using some virtual memory.
Instead, you usually want to allocate a buffer of reasonable size (say, a megabyte or two) then do the copying in a loop, something like:
char *buffer = malloc(1024 * 1024);
while ((bytes=fread(buffer, 1, sizeof(buffer), infile)) > 0)
fwrite(buffer, 1, bytes, outfile);
You can, of course, also check the return value from fwrite
and (for example) exit the loop if it doesn't write the amount you requested. This is particularly important if, for example, you're moving a file instead of just copying it -- you only want to remove the original when/if you're certain the copy has succeeded.
回答2:
You call ferror() to check the error status of an I/O stream if the fread/fwrite doesn't copy the number of chars you expect
回答3:
According to your posted code, I think you have made a mistake at this line.
fwrite(buffer, 1, file_size, file_to_copy);
you try to write something into the file_to_copy which is already closed, that is not allowed by program, so it gives you a stackoverflow.
来源:https://stackoverflow.com/questions/11054750/check-return-value-fread-and-fwrite