我在一些單元測試中就被這個問題困擾了。我想使用Inflater解壓縮一些 ZLIB 壓縮的數據,其中原始數據長度是預先知道的。這(簡單)按預期工作? ?/*??? ? ?* Decompresses a zlib compressed buffer, with given size of raw data.? ? ?* All data is fed and inflated in full (one step)?? ? ?*/? ? public static byte[] decompressFull(byte[] comp, int len) throws Exception {? ? ? ? byte[] res = new byte[len]; // result (uncompressed)? ? ? ? Inflater inf = new Inflater();? ? ? ? inf.setInput(comp);? ? ? ? int n = inf.inflate(res, 0, len);? ? ? ? if (n != len)? ? ? ? ? ? throw new RuntimeException("didn't inflate all data");? ? ? ? System.out.println("Data done (full). bytes in :"? + inf.getBytesRead()?? ? ? ? ? ? ? ? + " out=" + inf.getBytesWritten()? ? ? ? ? ? ? ? + " finished: " + inf.finished());? ? ? ? // done - the next is not needed, just for checking...?? ? ? ? //try a final inflate just in case (might trigger ZLIB crc check)? ? ? ? byte[] buf2 = new byte[6];? ? ? ? int nx = inf.inflate(buf2);//should give 0? ? ? ? if (nx != 0)? ? ? ? ? ? throw new RuntimeException("nx=" + nx + " " + Arrays.toString(buf2));? ? ? ? if (!inf.finished())? ? ? ? ? ? throw new RuntimeException("not finished?");? ? ? ? inf.end();? ? ? ? return res;? ? }現在,壓縮輸入可以是任意大小的塊。下面的代碼模擬了這樣一種情況:除了最后 4 個字節之外,壓縮輸入被全部饋送,然后一次饋送一個剩余字節。(據我了解,解壓縮完整數據不需要 zlib 流的最后 4 個或 5 個字節,但需要它們來檢查完整性 - Adler-32 CRC)。? ? public static byte[] decompressBytexByte(byte[] comp, int len) throws Exception {? ? ? ? ? ? byte[] res = new byte[len]; // result (uncompressed)? ? ? ? ? ? Inflater inf = new Inflater();? ? ? ? ? ? inf.setInput(comp, 0, comp.length - 4);? ? ? ? ? ? int n = inf.inflate(res, 0, len);? ? ? ? ? ? if (n != len)? ? ? ? }嗯,這對我不起作用(Java 1.8.0_181)。充氣機還沒有完成,Adler CRC 檢查還沒有完成,看起來;更多:似乎字節沒有送入充氣機。更奇怪的是:如果在一次調用中輸入尾部 4 個字節,它就會起作用。您可以在這里嘗試: https: //repl.it/@HernanJJ/Inflater-Test當我一次輸入一個字節的整個輸入時,甚至會發生更奇怪的事情:有時該行 int nx= inf.inflate(buf2);//should give 0返回非零(當所有數據已經被夸大時)。這是預期的行為嗎?我錯過了什么嗎?
1 回答

絕地無雙
TA貢獻1946條經驗 獲得超4個贊
正如@SeanBright
已經注意到的,你應該只在Inflater.needsInput()
返回 true 時為其提供新的輸入。
順序調用setInput
將覆蓋您之前傳遞的輸入。
Javadoc of Inflater.needsInput()
:
如果輸入緩沖區中沒有數據,則返回 true。這可用于確定是否應調用 #setInput 以提供更多輸入。
只要你逐字節地輸入它,情況總是如此,所以你可能可以跳過檢查本身。
您可以用此替換該方法的輸入設置部分decompressBytexByte
(用于完整的逐字節饋送):
byte[] res = new byte[len];
Inflater inf = new Inflater();
int a = 0; // number of bytes that have already been obtained
for (int p = 0; p < comp.length; p++) {? ? ? ? ?
? ? inf.setInput(comp, p, 1);
? ? a += inf.inflate(res, a, len - a);
}
添加回答
舉報
0/150
提交
取消