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.
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
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 coreutils
de que sea conveniente tomarlo y usarlo como biblioteca. Para ser honesto, probablemente termine ejecutando los binarios split
y join
como procesos secundarios desde mi programa principal.
Codiólogo
split
ycat
.ivanivan
split
yjoin
en elcoreutils
paquete de Debian