Empfehlen Sie eine C++-Bibliothek, um eine Datei in Chunks aufzuteilen und wieder zusammenzuführen?

Ich habe eine oder mehrere Eingabedateien, die eine Größe von bis zu 25 GB haben können. Der Dateityp kann ein Bild, ein Video, ein Text, eine Binärdatei usw. sein. Ich möchte wissen, ob es eine plattformübergreifende Bibliothek gibt, die eine Möglichkeit bietet, Dateien zu teilen/zu verbinden.

Oder ob es eine Klasse/Funktion in C++ gibt, die mir diese Art von Dienstprogramm bietet.

Warum nicht eines der üblichen E/A-Systeme von C++ verwenden? Lesen Sie die Datei ein und schreiben Sie sie in verschiedene Dateien, um sie aufzuteilen; Lesen Sie die Ausgabedateien zurück und verketten Sie sie, um sie zu verbinden. Oder rufen Sie die GNU-Coreutils splitund cat.
Sehen Sie sich die Quelle für splitund joinin Debians coreutilsPaket an

Antworten (1)

Wie @Kodiologist sagt, ist dies von Grund auf nicht allzu schwer:

Bearbeiten: Code vereinfachen. Leider ist die zusätzliche Komplexität durch die Möglichkeit, jeden Stream-Typ zu unterstützen, in diesem Zusammenhang nicht hilfreich.

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

Dies wird für mich in Visual Studio 2015 erstellt. Kein Grund, warum es nicht in jedem C++ 11-Compiler enthalten sein sollte (aber ich kann nicht versprechen, dass Sie keine kleineren Anpassungen vornehmen müssen).

Hier ist eine schnelle Plausibilitätsprüfung, ob die geteilte und verbundene Datei mit dem Original identisch ist

Vergleichen Sie md5-Dateien

Die Art von Fehler, nach der ich hier suche, ist genau der Grund, warum ich mich lieber auf erprobten und getesteten Code verlassen würde, aber ich bin nicht überzeugt, dass coreutilses bequem ist, ihn als Bibliothek zu greifen und zu verwenden. Um ehrlich zu sein, würde ich wahrscheinlich nur die Binärdateien splitund joinals untergeordnete Prozesse in meinem Hauptprogramm ausführen.