La copie de fichiers est une tâche courante en programmation. Il est essentiel d’aborder cette tâche avec à la fois bon sens et efficacité. Cet article explore diverses techniques de copie de fichiers en C tout en discutant de leurs avantages et inconvénients. Nous aborderons, entre autres, les fonctions C standard, les fonctions POSIX et les tampons de flux C.
Cette approche utilise les fonctions de bibliothèque standard C fread () et fwrite() pour lire et écrire des données en blocs. Bien qu'elle fournisse un contrôle de bas niveau, elle nécessite une gestion explicite du tampon et peut être verbeuse.
// ANSI-C-WAY #include <stdio.h> // fopen(), fclose(), fread(), fwrite(), BUFSIZ #include <cstdio> // size_t using namespace std; int main() { // Define buffer size (BUFSIZE default is 8192 bytes) const size_t BUFFER_SIZE = 4096; char buf[BUFFER_SIZE]; size_t size; FILE* source = fopen("from.ogv", "rb"); FILE* dest = fopen("to.ogv", "wb"); while (size = fread(buf, 1, BUFFER_SIZE, source)) { fwrite(buf, 1, size, dest); } fclose(source); fclose(dest); return 0; }
Cette approche utilise la lecture POSIX( ) et les fonctions write(), offrant plus de contrôle sur les opérations sur les fichiers que l'approche ANSI C. Il offre la possibilité de gérer des fichiers plus volumineux et de gérer les erreurs plus méticuleusement.
// POSIX-WAY #include <fcntl.h> // open() #include <unistd.h> // read(), write(), close() #include <stdio.h> // BUFSIZ using namespace std; int main() { // Define buffer size (BUFSIZE default is 8192 bytes) const size_t BUFFER_SIZE = 4096; char buf[BUFFER_SIZE]; size_t size; int source = open("from.ogv", O_RDONLY, 0); int dest = open("to.ogv", O_WRONLY | O_CREAT | O_TRUNC, 0644); while ((size = read(source, buf, BUFFER_SIZE)) > 0) { write(dest, buf, size); } close(source); close(dest); return 0; }
Cette approche tire parti des tampons de flux d'E/S C. C'est concis et simple, utilisant la méthode rdbuf() pour copier l'intégralité du fichier, laissant le runtime C gérer les E/S de bas niveau.
// KISS-C++-Streambuffer-WAY #include <iostream> // cout, cin #include <fstream> // ifstream, ofstream using namespace std; int main() { ifstream source("from.ogv", ios::binary); ofstream dest("to.ogv", ios::binary); dest << source.rdbuf(); source.close(); dest.close(); return 0; }
L'algorithme C copy() peut copier efficacement les données d'un fichier à un autre. Cette approche bénéficie des itérateurs robustes de la STL, éliminant le besoin de gérer manuellement la gestion des tampons.
// COPY-ALGORITHM-C++-WAY #include <iostream> // cout, cin #include <fstream> // ifstream, ofstream #include <ctime> // clock_t, clock() #include <algorithm> // copy #include <iterator> // istreambuf_iterator, ostreambuf_iterator using namespace std; int main() { ifstream source("from.ogv", ios::binary); ofstream dest("to.ogv", ios::binary); istreambuf_iterator<char> begin_source(source); istreambuf_iterator<char> end_source; ostreambuf_iterator<char> begin_dest(dest); copy(begin_source, end_source, begin_dest); source.close(); dest.close(); return 0; }
Cette approche alloue son propre tampon, offrant un contrôle précis sur la gestion de la mémoire et la taille de la mémoire tampon. Cela nécessite une désallocation de mémoire minutieuse pour éviter les fuites.
// OWN-BUFFER-C++-WAY #include <iostream> // cout, cin #include <fstream> // ifstream, ofstream #include <ctime> // clock_t, clock() using namespace std; int main() { ifstream source("from.ogv", ios::binary); ofstream dest("to.ogv", ios::binary); // Determine file size and allocate buffer source.seekg(0, ios::end); ifstream::pos_type size = source.tellg(); source.seekg(0, ios::beg); char* buffer = new char[size]; // Copy file source.read(buffer, size); dest.write(buffer, size); // Cleanup delete[] buffer; source.close(); dest.close(); return 0; }
La fonction sendfile() spécifique à Linux tire parti de l'optimisation au niveau du noyau et du transfert direct de données. entre les descripteurs de fichiers. Cette approche est connue pour son efficacité, en particulier sur les transferts de fichiers volumineux.
// LINUX-WAY #include <iostream> // cout, cin #include <sys/sendfile.h> // sendfile #include <fcntl.h> // open #include <unistd.h> // close #include <sys/stat.h> // stat #include <sys/types.h> // stat #include <ctime> // clock_t, clock() using namespace std; int main() { int source = open("from.ogv", O_RDONLY, 0); int dest = open("to.ogv", O_WRONLY | O_CREAT | O_TRUNC, 0644); // Determine file size struct stat stat_source; fstat(source, &stat_source); // Copy file sendfile(dest, source, 0, stat_source.st_size); close(source); close(dest); return 0; }
Les approches proposées varient en complexité, en efficacité et en contrôle. Voici un résumé de leurs forces et limites :
Approach | Pros | Cons |
---|---|---|
ANSI C | Low-level control, portable | Verbose, buffer management required |
POSIX | More control than ANSI C, handles large files | Still requires explicit buffer management |
KISS-C -Streambuffer | Concise, stream buffer manages I/O | High-level, less control over buffering |
COPY-ALGORITHM-C | Efficient, STL iterators handle data transfer | Requires caution with large files to avoid buffering issues |
OWN-BUFFER-C | Fine-grained control over buffer management | Memory management must be handled carefully to avoid leaks |
LINUX-sendfile() | Fast, kernel-level optimization | Linux-specific, requires elevated privileges |
Le choix de la meilleure approche dépend des exigences spécifiques de votre application. Pour les petits fichiers, la simplicité de ifstream/ofstream peut suffire. Pour les fichiers volumineux ou les scénarios où l’efficacité est cruciale, sendfile() est une excellente option. En fin de compte, il est recommandé de tester et d'évaluer différentes approches pour déterminer la solution optimale pour votre cas d'utilisation.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!