-->

如何报告上QuaGzipFile读取数据的进度(QuaZIP库)(how to report pro

2019-10-19 05:28发布

我在Ubuntu 12.04使用x86_64的0.5.1 QuaZIP使用Qt 5.1.1 C ++。

我的程序读取一个大的gzip压缩的二进制文件,通常是未压缩数据或更多的1GB内存,并使得它的一些计算。 这是不计算-广泛,大部分时间是在I / O通过。 所以,如果我能找到一种方法来报告文件的多少数据被读取,我可以在进度条上的举报,甚至提供ETA的估计。

我打开该文件:

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

但在QuaGzipFile没有功能来查找文件的大小,也不是当前位置。

我并不需要找到的大小和未压缩的流的位置,大小和压缩数据流的位置都很好,因为进步的粗略估计是不够的。

目前,我能找到的压缩文件的大小 ,使用QFile(fileName).size() 另外,我可以很容易地找到未压缩的流的当前位置 ,通过保持的返回值的总和gzip.read() 但是,这两个数字不匹配。

我可以改变QuaZIP库,并访问内部的zlib相关的东西,如果它帮助。

Answer 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的可以在内部读取和解码更多的数据比你已经读过。



Answer 2:

在zlib的1.2.4和更大的可使用gzoffset()函数来得到压缩文件中的当前位置。 zlib的当前版本是1.2.8。



Answer 3:

使用一个丑陋的黑客攻击为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();


文章来源: how to report progress of data read on a QuaGzipFile (QuaZIP library)