QZipWriter повреждает архивы при работе с большими файлами
Мне необходимо архивировать (со сжатием или без - не принципиально) файлы разной величины, для этого я (в рамках работы на Qt) использовал незадокументированный QZipWriter, который, как мне казалось, хорошо работал, пока я тестировал его на маленьких данных (до 3гб), но стоило мне попробовать сжать папку на 16гб (каждый файл я сжимаю по отдельности, так как не нашёл в qzip возможности сжимать разом папки), как возникают CRC-ошибки контрольных сумм при попытке открыть архив (при этом сам QZipWriter видимых ошибок не выдаёт).
Вот, как я архивирую отдельный файл:
QFile file(filepath);
if (!file.open(QIODevice::ReadOnly))
return false;
QString correctDirName = relativePath;
if (!correctDirName.isEmpty() && correctDirName.back() != QDir::separator()) {
correctDirName.push_back(QDir::separator());
}
_zip->addFile(correctDirName + QFileInfo(filepath).fileName(), file.readAll());
file.close();
_progressedBytes += QFileInfo(filepath).size();
updateProgressBar();
return true;
Вот, как я архивирую папку (надо сказать, что папка заведомо имеет определённую сигнатуру, так что я при архивации, как вы можете видеть, ориентируюсь именно на неё):
QDir dir = QDir(path);
if (!dir.cdUp()) {
emit message(ReportingMessage::BAD_PROJECT_WAY);
return false;
}
QString projectDirName = dir.dirName();
QFileInfoList dirContent = dir.entryInfoList();
for each (const auto& var in dirContent) //Сжатие всех файлов в папке проекта
{
if (_stoped) {
_reportingResult = ReportingResult::CANCELED;
return false;
}
if (!var.isDir())
compressFile(var.absoluteFilePath(), projectDirName);
}
if (dirContent.front().isDir()) //Сжатие всех файлов в папке Temp (если она есть)
{
QFileInfo tmpFolder = dirContent.back();
if (tmpFolder.fileName() != TmpDirName) {
emit message(ReportingMessage::UNEXPECTED_PROJECT_SGINATURE);
return false;
}
dirContent = QDir(tmpFolder.absoluteFilePath()).entryInfoList();
for each (const auto & var in dirContent)
{
if (_stoped) {
_reportingResult = ReportingResult::CANCELED;
return false;
}
if (!var.isDir())
compressFile(var.absoluteFilePath(), projectDirName + QDir::separator() + TmpDirName);
}
}
return true;
У меня есть подозрение, что метод архивации файла можно как-либо модифицировать, чтобы он был более отказоустойчивым.
Ответы (1 шт):
Решается переходом на любую библиотеку, например miniz:
#include <miniz/miniz.h>
#include <miniz/miniz_zip.h>
// обжимает data размером size, результат выгружает в result, возвращает размер result
size_t zip(void** result, const char* data, const size_t size)
{
struct zip_t* zip = zip_stream_open(nullptr, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
{
zip_entry_open(zip, "frac_project");
{
zip_entry_write(zip, data, size);
}
zip_entry_close(zip);
}
const int resultSize(zip_stream_copy(zip, result, nullptr));
zip_stream_close(zip);
return resultSize;
}
// принимает массив байт, возвращает его же в сжатом виде
QByteArray& compress(const QByteArray &data)
{
QByteArray out;
void* result;
const int resultSize(zip(&result, data.data(), data.size()));
out.setRawData(static_cast<char*>(result), resultSize);
return out;
}