11

私はGZIPInputStream別のものから構築したものを持っていByteArrayInputStreamます。gzipデータの元の(圧縮されていない)長さを知りたい。の最後まで読んでGZIPInputStream数を数えることはできますが、時間とCPUの浪費になります。読む前にサイズを知りたいのですが。

ZipEntry.getSize()次のような同様の方法はありますかGZIPInputStream

public long getSize ()
以来: APIレベル1
このZipEntryの非圧縮サイズを取得します。

4

8 に答える 8

8

gzipで圧縮されたファイルの最後の4バイトを読み取ることにより、非圧縮サイズを判別できます。

私はここでこの解決策を見つけました:

http://www.abeel.be/content/determine-uncompressed-size-gzip-file

また、このリンクからいくつかのサンプルコードがあります(ラップアラウンドを行う2GBから4GBの間のサイズに対処するために、longの代わりに使用するように修正されました):intint

RandomAccessFile raf = new RandomAccessFile(file, "r");
raf.seek(raf.length() - 4);
byte b4 = raf.read();
byte b3 = raf.read();
byte b2 = raf.read();
byte b1 = raf.read();
long val = ((long)b1 << 24) | ((long)b2 << 16) | ((long)b3 << 8) | (long)b4;
raf.close();

valバイト単位の長さです。注意:非圧縮ファイルが4GBを超える場合、正しい非圧縮サイズを判別することはできません。

于 2011-09-23T12:31:11.843 に答える
6

@Alexanderの回答に基づく:

RandomAccessFile raf = new RandomAccessFile(inputFilePath + ".gz", "r");
raf.seek(raf.length() - 4);
byte[] bytes = new byte[4];
raf.read(bytes);
fileSize = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
if (fileSize < 0)
  fileSize += (1L << 32);
raf.close();
于 2012-10-02T04:31:59.707 に答える
2

GZIPInputStreamのZipEntry.getSize()のような同様のメソッドはありますか

いいえ。Javadocにはありません=>存在しません。

あなたは何のための長さが必要ですか?

于 2011-09-06T09:34:10.730 に答える
2

圧縮率(データが既に処理した他のデータと類似している場合の妥当な予想)を推測できる場合は、任意の大きなファイルのサイズを計算できます(エラーが発生します)。繰り返しますが、これは単一のgzipストリームを含むファイルを想定しています。以下は、(推定比率に基づいて)推定サイズの90%を超える最初のサイズが実際のサイズであると想定しています。

estCompRatio = 6.1;
RandomAccessFile raf = new RandomAccessFile(inputFilePath + ".gz", "r");
compLength = raf.length();
byte[] bytes = new byte[4];
raf.read(bytes);
uncLength = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
raf.seek(compLength - 4);
uncLength = raf.readInt();
while(uncLength < (compLength * estCompRatio * 0.9)){
  uncLength += (1L << 32);
}

[estCompRatioを0に設定することは、@Alexanderの回答と同等です]

于 2012-10-29T04:23:48.603 に答える
2

4つのテールバイトに基づく計算のよりコンパクトなバージョン(バイトバッファの使用を避けInteger.reverseBytes、読み取られたバイトのバイト順序を逆にするための呼び出し)。

private static long getUncompressedSize(Path inputPath) throws IOException
{
    long size = -1;
    try (RandomAccessFile fp = new RandomAccessFile(inputPath.toFile(), "r")) {        
        fp.seek(fp.length() - Integer.BYTES);
        int n = fp.readInt();
        size = Integer.toUnsignedLong(Integer.reverseBytes(n));
    }
    return size;
}
于 2018-04-05T21:45:58.687 に答える
1

全体を解凍する以外に、長さを取得する信頼できる方法はありません。zlibのgzipファイルアクセス機能を使用した非圧縮ファイルサイズを参照してください。

于 2012-10-02T04:38:48.430 に答える
0

代わりに、基になるFileInputStreamからFileChannelを取得してください。圧縮ファイルのファイルサイズと現在の位置の両方が表示されます。例:

@Override
public void produce(final DataConsumer consumer, final boolean skipData) throws IOException {
    try (FileInputStream fis = new FileInputStream(tarFile)) {
        FileChannel channel = fis.getChannel();
        final Eta<Long> eta = new Eta<>(channel.size());
        try (InputStream is = tarFile.getName().toLowerCase().endsWith("gz")
            ? new GZIPInputStream(fis) : fis) {
            try (TarArchiveInputStream tais = (TarArchiveInputStream) new ArchiveStreamFactory()
                .createArchiveInputStream("tar", new BufferedInputStream(is))) {

                TarArchiveEntry tae;
                boolean done = false;
                while (!done && (tae = tais.getNextTarEntry()) != null) {
                    if (tae.getName().startsWith("docs/") && tae.getName().endsWith(".html")) {
                        String data = null;
                        if (!skipData) {
                            data = new String(tais.readNBytes((int) tae.getSize()), StandardCharsets.UTF_8);
                        }
                        done = !consumer.consume(data);
                    }

                    String progress = eta.toStringPeriodical(channel.position());
                    if (progress != null) {
                        System.out.println(progress);
                    }
                }
                System.out.println("tar bytes read: " + tais.getBytesRead());
            } catch (ArchiveException ex) {
                throw new IOException(ex);
            }
        }
    }
}
于 2019-02-18T05:24:57.953 に答える
-1

いいえ、残念ながら、非圧縮サイズを取得したい場合は、質問で述べたように、ストリーム全体を読み取り、カウンターをインクリメントする必要があります。なぜサイズを知る必要があるのですか?サイズの見積もりはあなたの目的のために働くことができますか?

于 2011-09-06T13:29:38.700 に答える