1

Ubuntu 12.04 x86_64 で C++ 用の Qt 5.1.1 で QuaZIP 0.5.1 を使用しています。

私のプログラムは、gzip で圧縮された大きなバイナリ ファイル (通常は 1 GB 以上の圧縮されていないデータ) を読み取り、その上でいくつかの計算を行います。計算量は多くなく、ほとんどの時間は I/O で渡されます。そのため、ファイルのデータの読み取り量を報告する方法を見つけることができれば、進行状況バーで報告し、ETA の見積もりを提供することもできます。

私はファイルを開きます:

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

ただし、QuaGzipFile には、ファイル サイズや現在の位置を見つける機能はありません。

非圧縮ストリームのサイズと位置を見つける必要はありません。進行状況の大まかな見積もりで十分なので、圧縮ストリームのサイズと位置は問題ありません。

現在、を使用して、圧縮ファイルのサイズを見つけることができますQFile(fileName).size()。また、の戻り値の合計を保持することで、圧縮されていないストリーム内の現在の位置を簡単に見つけることができますgzip.read()。しかし、これら 2 つの数値は一致しません。

必要に応じて、QuaZIP ライブラリを変更し、内部の zlib 関連のものにアクセスできます。

4

3 に答える 3

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 が、既に読み取ったデータよりも多くのデータを内部的に読み取ってデコードできるためです。

于 2014-01-13T13:14:06.373 に答える
1

zlib 1.2.4 以降では、gzoffset()関数を使用して圧縮ファイル内の現在の位置を取得できます。zlib の現在のバージョンは 1.2.8 です。

于 2014-01-13T14:04:54.357 に答える
0

zlib への醜いハックを使用して、圧縮ストリーム内の位置を見つけることができました。

まず、gz_streamgzio.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();
于 2014-01-13T12:43:55.603 に答える