¿Recomendar la biblioteca de C++ para dividir un archivo en fragmentos y fusionarlo nuevamente?

Tengo un archivo de entrada que puede tener un tamaño de hasta 25 GB. El tipo de archivo puede ser una imagen, video, texto, binario, etc. Quiero saber si hay una biblioteca multiplataforma que proporcione una forma de dividir/unir archivos.

O si hay una clase/función en C++ que me proporcione este tipo de utilidad.

¿Por qué no usar cualquiera de los sistemas de E/S habituales de C++? Lea el archivo y escríbalo en diferentes archivos para dividir; lea los archivos de salida y concatene para unirse. O llame a GNU coreutils splity cat.
Mire la fuente para splity joinen el coreutilspaquete de Debian

Respuestas (1)

Como dice @Kodiologist, esto no es demasiado difícil de hacer desde los primeros principios:

Editar: simplificar el código. Desafortunadamente, la complejidad adicional de poder soportar cualquier tipo de transmisión no es útil en este contexto.

#include <fstream>
#include <memory>
#include <sstream>
#include <vector>

const int size1MB = 1024 * 1024;

std::unique_ptr<std::ofstream> createChunkFile(std::vector<std::string>& vecFilenames) {
    std::stringstream filename;
    filename << "chunk" << (vecFilenames.size() + 1) << ".txt";
    vecFilenames.push_back(filename.str());
    return std::make_unique<std::ofstream>(filename.str(), std::ios::trunc);
}

void split(std::istream& inStream, int nMegaBytesPerChunk, std::vector<std::string>& vecFilenames) {

    std::unique_ptr<char[]> buffer(new char[size1MB]);
    int nCurrentMegaBytes = 0;

    std::unique_ptr<std::ostream> pOutStream = createChunkFile(vecFilenames);

    while (!inStream.eof()) {
        inStream.read(buffer.get(), size1MB);
        pOutStream->write(buffer.get(), inStream.gcount());
        ++nCurrentMegaBytes;
        if (nCurrentMegaBytes >= nMegaBytesPerChunk) {
            pOutStream = createChunkFile(vecFilenames);
            nCurrentMegaBytes = 0;
        }
    }

}

void join(std::vector<std::string>& vecFilenames, std::ostream& outStream) {
    for (int n = 0; n < vecFilenames.size(); ++n) {
        std::ifstream ifs(vecFilenames[n]);
        outStream << ifs.rdbuf();
    }
}

void createTestFile(const std::string& filename) {
    std::ofstream ofs(filename, std::ios::trunc);

    std::unique_ptr<char[]> buffer(new char[size1MB]);

    int i = 0;

    for (int n = 0; n < 1024; ++n) {
        for (int m = 0; m < size1MB; ++m) {
            buffer[m] = 'a' + (i++ % 26);
        }

        ofs.write(buffer.get(), size1MB);
    }
}

int main()
{

    // Create test file

    std::string filenameBefore = "before-big.txt";
    createTestFile(filenameBefore);

    // Split

    std::ifstream ifs(filenameBefore);
    std::vector<std::string> vecFilenames;

    split(ifs, 100, vecFilenames);

    // Join

    std::string filenameAfter = "after-big.txt";

    std::ofstream ofs(filenameAfter, std::ios::trunc);
    join(vecFilenames, ofs);

    return 0;
}

Esto se compila para mí en Visual Studio 2015. No hay razón por la que no deba estar en ningún compilador de C++ 11 (pero no puedo prometer que no tendrá que hacer ajustes menores).

Aquí hay una verificación rápida de la cordura de que el archivo dividido y unido es el mismo que el original

comparar archivos md5

El tipo de error que estoy buscando aquí es exactamente la razón por la que preferiría confiar en el código probado y probado, pero no estoy convencido coreutilsde que sea conveniente tomarlo y usarlo como biblioteca. Para ser honesto, probablemente termine ejecutando los binarios splity joincomo procesos secundarios desde mi programa principal.