亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

這是 Java 的 Inflater 中的錯誤還是什么?

這是 Java 的 Inflater 中的錯誤還是什么?

鴻蒙傳說 2023-08-16 09:46:35
我在一些單元測試中就被這個問題困擾了。我想使用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);

}


查看完整回答
反對 回復 2023-08-16
  • 1 回答
  • 0 關注
  • 137 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號