Copier un fichier dans un autre (Unix / C)?

J’ai écrit le code suivant pour copier un fichier dans un autre. Bien que le code fonctionne, le code affiche toujours les deux messages d’erreur. Pourquoi est-ce ? Je suis un débutant en programmation Unix et C (bien que j’ai déjà travaillé avec C ++), une aide aussi détaillée que possible serait très utile. Merci !

int main(int argc, char *argv[]) { int n; char buf[4096]; while ((n=read( open(argv[1], O_RDONLY) , buf, 4096))>0) { if (write(creat(argv[2], S_IREAD | S_IWRITE ), buf, n)!=n) printf("Error writing to file.\n"); } if (n<0) printf("Error reading from file.\n"); exit(0); } 

Vous ouvrez le fichier à chaque itération et essayez de le creat à chaque itération.

Donc, à l’exception de la toute première itération, toutes les écritures suivantes échoueront. Cela “semble probablement fonctionner” car votre fichier d’entrée contient moins de 4096 octets. Le premier appel à écrire a donc été de faire en sorte que tout soit copié. Si vous utilisez une entrée de plus de 4096 octets, vous ne verrez que les 4096 premiers octets (en supposant que read() et write() ne manquent pas).

Si write() devait réussir tout le temps (par exemple, vous aviez le creat() dehors de la boucle), l’appel open() ouvre en permanence le même fichier et est potentiellement une boucle infinie, sinon votre système manquerait de descripteur de fichier et renverrait un descripteur de fichier invalide et read() échoueront sur cela.

Longue histoire courte: n’écris pas de code comme ça 🙂

Déplacez les deux appels vers open() et creat() dehors de la boucle:

 int fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); exit(1); } int fd2 = creat(argv[2], S_IREAD | S_IWRITE ); if (fd2 == -1) { perror("write"); exit(1); } while ( (n=read( fd , buf, 4096)) > 0 ) { if ( write(fd2 , buf, n) != n ) printf("Error writing to file.\n"); } 

La réponse ci-dessus a été détectée, cependant, il convient de ne pas utiliser creat (), car create () est une fonction obsolète. créer (nom du fichier, mode); est équivalent à open (nomfichier, O_WRONLY | O_CREAT | O_TRUNC, mode);

http://www.gnu.org/software/libc/manual/html_node/Opening-and-Closing-Files.html

Le code pourrait être mieux écrit comme:

 #include  #include  #include  #include  #include  #define BUFSIZE 4096 int main(int argc, char **argv) { int infd, outfd; int n; char *infile = NULL; char *outfile = NULL; int src_flags, dest_flags; mode_t dest_perms; char buf[BUFSIZE]; if (argc < 3) { fprintf(stderr, "At least src and dest files must be specified\n"); /*Never rely on users' inputs*/ /*Print usage information if possible*/ exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; /*Presuming the order*/ src_flags = O_RDONLY; dest_flags = O_CREAT | O_WRONLY | O_TRUNC; /*creat() is equivalent to open(fname, O_CREAT | O_WRONLY | O_TRUNC, mode)*/ dest_perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /*rw-rw-rw-*/ infd = open(infile, src_flags); if (infd == -1) { perror("cannot open src "); exit(EXIT_FAILURE); } outfd = open(outfile, dest_flags, dest_perms); if (outfd == -1) { perror("cannot open dest "); exit(EXIT_FAILURE); } while ((n = read(infd, buf, BUFSIZE)) > 0) { if (write(outfd, buf, n) != n) { fprintf(stderr, "failed to write buf\n"); goto exit_failure; } } if (n == -1) { fprintf(stderr, "read() failed\n"); goto exit_failure; } exit_failure: if (infd) { close(infd); } if (outfd) { close(outfd); } printf("Copy successful\n"); exit(EXIT_SUCCESS); }