Как сообщить о ходе чтения данных в QuaGzipFile (библиотека QuaZIP)

Я использую QuaZIP 0.5.1 с Qt 5.1.1 для C ++ в Ubuntu 12.04 x86_64.

Моя программа читает большой сжатый двоичный файл, обычно 1 ГБ несжатых данных или более, и выполняет на нем некоторые вычисления. Он не требует больших вычислительных ресурсов и большую часть времени отводится на ввод-вывод. Поэтому, если я могу найти способ сообщить, сколько данных файла прочитано, я могу сообщить об этом на индикаторе выполнения и даже дать оценку ETA.

Я открываю файл с:

QuaGzipFile gzip(fileName);
if (!gzip.open(QIODevice::ReadOnly))
{
// report error
return;
}

Но в QuaGzipFile нет функциональности для определения размера файла или текущей позиции.

Мне не нужно находить размер и положение несжатого потока, размер и положение сжатого потока хороши, потому что достаточно грубой оценки прогресса.

В настоящее время я могу найти размер сжатого файла, с помощью QFile(fileName).size(), Кроме того, я могу легко найти текущая позиция в несжатом потоке, сохраняя сумму возвращаемых значений gzip.read(), Но эти два числа не совпадают.

Я могу изменить библиотеку QuaZIP и получить доступ к внутренним материалам, связанным с zlib, если это поможет.

1

Решение

Не существует надежного способа определения общего размера несжатого потока. Увидеть этот ответ для деталей и возможных обходных путей.

Однако есть способ получить позицию в сжатом потоке:

QFile file(fileName);
file.open(QFile::ReadOnly);
QuaGzipFile gzip;
gzip.open(file.handle(), QuaGzipFile::ReadOnly);
while(true) {
QByteArray buf = gzip.read(1000);
//process buf
if (buf.isEmpty()) { break; }
QFile temp_file_object;
temp_file_object.open(file.handle(), QFile::ReadOnly);
double progress = 100.0 * temp_file_object.pos() / file.size();
qDebug() << qRound(progress) << "%";
}

Идея состоит в том, чтобы открыть файл вручную и использовать дескриптор файла, чтобы получить позицию. QFile не может отслеживать внешние изменения позиции, поэтому file.pos() будет всегда 0. Таким образом, мы создаем temp_file_object из файлового дескриптора, заставляя QFile запрашивать позицию файла. Я мог бы использовать API более низкого уровня (например, lseek()), чтобы получить позицию файла, но я думаю, что мой путь более кроссплатформенный.

Обратите внимание, что этот метод не очень точен и может давать значения прогресса больше, чем реальные. Это потому, что zlib может внутренне читать и декодировать больше данных, чем вы уже прочитали.

1

Другие решения

В zlib 1.2.4 и выше вы можете использовать gzoffset() функция, чтобы получить текущую позицию в сжатом файле. Текущая версия zlib — 1.2.8.

1

Используя некрасивый хак к zlib, я смог найти позицию в сжатом потоке.

Во-первых, я скопировал определение gz_stream от gzio.c (из источника zlib-1.2.3.4) до конца quagzipfile.cpp. Затем я переопределил виртуальную функцию qint64 QIODevice::pos() const:

qint64 QuaGzipFile::pos() const
{
gz_stream *s = (gz_stream *)d->gzd;
return ftello64(s->file);
}

Поскольку quagzipfile.cpp и quagzipfile.h кажутся независимыми от других библиотечных файлов QuaZIP, может быть, лучше скопировать нужные мне функции из этих файлов и избежать этого взлома?

Текущая версия программы выглядит примерно так:

QFile infile(fileName);
if (!infile.open(QIODevice::ReadOnly))
return;
qint64 fileSize = infile.size;
infile.close();

QuaGzipFile gzip(fileName);
if (!gzip.open(QIODevice::ReadOnly))
return;
qint64 nread;
char buffer[bufferSize];
while ((nread = gzip.read(&buffer, bufferSize)) > 0)
{
// use buffer
int percent = 100.0 * gzip.pos() / fileSize;
// report percent
}
gzip.close();
0
По вопросам рекламы [email protected]