Maison >développement back-end >C++ >Quelles sont les meilleures méthodes pour copier rapidement et en toute sécurité des fichiers en C, et quels sont leurs avantages et inconvénients respectifs ?

Quelles sont les meilleures méthodes pour copier rapidement et en toute sécurité des fichiers en C, et quels sont leurs avantages et inconvénients respectifs ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-25 03:29:20540parcourir

What are the best methods for safely and quickly copying files in C  , and what are their respective advantages and disadvantages?

Copier des fichiers en toute sécurité et rapidement en C

Présentation

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.

Approche ANSI C : fread() et fwrite()

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;
}

Approche POSIX : read() et write()

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;
}

Approche KISS-C -Streambuffer : tampons de flux

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;
}

Approche COPY-ALGORITHM-C : algorithme copy()

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;
}

Approche OWN-BUFFER-C : propre gestion des tampons

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;
}

Approche LINUX : fonction sendfile()

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;
}

Comparaison et conclusion

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn