#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: he actualizado el código de
tengo algunas dudas:

1) tengo que revisar el código de retorno de fread porque – por ejemplo – si bytes convertido en 0 debido a un error, 0 se escribirá en el archivo copiado.
Pero mi pregunta es: ¿cómo hacerlo? Porque fread puede return 0 pero también puede devolver un corto valor ….

2) ¿cómo se puede leer ir a través del archivo? Si puedo copiar un archivo de 5MB cómo puede fread pasar de 1MB en 1MB sin algo que decir a él «hey usted tiene que poner su desplazamiento 1MB después de la 1MB usted acaba de copiar»?

3) ¿por qué no limpiar el buffer después de cada uso? Me refiero a algo como:

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));
}
  • intente almacenar en size_t en lugar de int
  • desbordamiento de pila 🙁
  • Yo normalmente uso fread(buffer, file_size, 1, file_to_copy), y comprobar el retorno de fread si es igual a 1
InformationsquelleAutor polslinux | 2012-06-15

3 Comentarios

  1. 4

    Por lo general, usted no quiere intentar copiar un archivo completo en una sola lectura/escritura de ciclo. Esto tiene (entre otras cosas) de una forma bastante sustancial de la oportunidad de la asignación de memoria en su defecto, o ser terriblemente ineficiente si al final asignar y utilizar algunos de la memoria virtual.

    Lugar, normalmente se desea asignar un búfer de tamaño razonable (es decir, un megabyte o dos) y luego hacer la copia en un bucle, algo así como:

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

    Usted puede, por supuesto, también para comprobar el valor de retorno de fwrite y (por ejemplo) salir del bucle si no escribe la cantidad que usted pidió. Esto es particularmente importante si, por ejemplo, va a mover un archivo, en lugar de copiar-usted sólo desea quitar el original cuando/si está seguro de que la copia se ha realizado correctamente.

    • pero, ¿cómo puedo verificar el valor de retorno de fwrite? Tengo un desbordamiento de pila 🙁
    • pero, ¿por qué usted comprobar bytes > 0 ? ¿Fread return 0 cuando se llegue a la EF? Y también por qué no está «claro» que el búfer antes de volver a utilizarlos?
    • devuelve el número de elementos que se lea correctamente, por lo que podemos escribir que el número de vuelta. Sí, cuando no puede leer nada se devuelve 0 (sin importar si son de fin de archivo o alguna otra cosa, como un error de disco). No es necesario borrar el búfer, porque la única parte que se utiliza es la parte que fread acababa de escribir.
    • Ah ok yo he entendido…pero lo que no unserstand es: si asignamos 1MB para el búfer y se escribe 1 MB en el búfer, la próxima vez que escriba en él – por ejemplo – 400KB hay otros 600KB que se han escrito y están sucios…o el malloced búfer no funciona como matriz??
    • Mire cuidadosamente-guardamos el valor de retorno de fread en bytes. Cuando llamamos a fwrite, pasamos bytes (es decir, la cantidad que fue leído) en cuanto a la cantidad a escribir. Así, si leemos todo el búfer completo, que es lo que escribir, pero si sólo nos lea un parcial de búfer, que es lo que escribir.
    • ok..yo he entendido ahora 😀 muchas gracias 😀 lo que no se entienda es: ¿cómo puede fread recorrer el archivo? Si puedo copiar un archivo de 5MB cómo puede fread pasar de 1MB en 1MB sin algo que decir a él «hey usted tiene que poner su desplazamiento 1MB después de la 1MB usted acaba de copiar»?
    • Cada archivo (que se abre en C) tiene una «posición actual» puntero. Cuando se lee, que es donde usted lee. Cuando usted escribe, que es donde se escribe. En cualquier momento de leer o escribir, se actualiza a la nueva posición (es decir, después de lo que acaba de leer/escribió).
    • aaaaaaaaaaaaah ok, ahora todo está claro 🙂 muchas gracias!!!

  2. 1

    Llamar ferror() para comprobar el estado de error de una secuencia de e/S si el fread/fwrite no copia el número de caracteres que usted espera

    • oh gracias! Esto puede ser bueno 🙂 EDIT: esto es correcto? while ((bytes=fread(buffer, 1, sizeof(buffer), file_to_copy)) > 0){ fwrite(buffer, 1, bytes, new_file); if(ferror(new_file){ printf("Errore scrittura\n"); fclose(file_to_copy); fclose(new_file); exit(1); } }
    • sí, ver también perror() imprime el real mensaje de error del sistema que ferror() encontrado
    • Ok, muchas gracias 🙂
  3. 1

    De acuerdo a su código publicados, creo que han cometido un error en esta línea.

    fwrite(buffer, 1, file_size, file_to_copy);

    intenta escribir algo en el file_to_copy que ya está cerrado, que no está permitido por el programa, por lo que le da un stackoverflow.

    • O. o soy un idiota xD el más mínimo error es siempre la más difícil de encontrar 😀

Dejar respuesta

Please enter your comment!
Please enter your name here