2011-03-11 73 views
10

我注意到我的一些gzip解碼代碼似乎無法檢測到損壞的數據。我認爲我已經將問題追溯到Java GZipInputStream類。特別是,當你用單個「讀取」調用讀取整個流時,損壞的數據不會觸發IOException。如果您在兩次或多次調用中讀取了同一個已損壞數據的流,則會觸發異常。這是Java GZipInputStream類中的錯誤嗎?

我想看看社區在考慮提交bug報告之前想到了什麼。

編輯:我修改了我的例子,因爲最後一個沒有清楚地說明我認爲是什麼問題。在這個新例子中,一個10字節的緩衝區被壓縮,一個被壓縮的緩衝區的一個字節被修改,然後它被解壓縮。對'GZipInputStream.read'的調用返回10作爲讀取的字節數,這是您對10字節緩衝區的期望值。儘管如此,解壓縮緩衝區與原始緩衝區不同(由於損壞)。沒有例外被拋出。我確實注意到在讀取之後調用'available'會返回'1',而不是'0',如果EOF已經達到,它將會返回。

這裏是源:

@Test public void gzip() { 
    try { 
     int length = 10; 
     byte[] bytes = new byte[]{12, 19, 111, 14, -76, 34, 60, -43, -91, 101}; 
     System.out.println(Arrays.toString(bytes)); 

     //Gzip the byte array 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     GZIPOutputStream gos = new GZIPOutputStream(baos); 
     gos.write(bytes); 
     gos.finish(); 
     byte[] zipped = baos.toByteArray(); 

     //Alter one byte of the gzipped array. 
     //This should be detected by gzip crc-32 checksum 
     zipped[15] = (byte)(0); 

     //Unzip the modified array 
     ByteArrayInputStream bais = new ByteArrayInputStream(zipped); 
     GZIPInputStream gis = new GZIPInputStream(bais); 
     byte[] unzipped = new byte[length]; 
     int numRead = gis.read(unzipped); 
     System.out.println("NumRead: " + numRead); 
     System.out.println("Available: " + gis.available()); 

     //The unzipped array is now [12, 19, 111, 14, -80, 0, 0, 0, 10, -118]. 
     //No IOException was thrown. 
     System.out.println(Arrays.toString(unzipped)); 

     //Assert that the input and unzipped arrays are equal (they aren't) 
     org.junit.Assert.assertArrayEquals(unzipped, bytes); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    } 
+1

+1好問題;寫得很好,帶有自包含,簡潔的RUNNABLE示例。這就是爲什麼你得到這樣一個快速答案:-) – 2011-03-11 18:26:03

回答

9

決定進行測試:

什麼你已經錯過了。 gis.read(unzipped)返回1,因此它只讀取一個字節。你不能抱怨,這不是流的結束。

未來read()投擲「腐敗的GZIP拖車」

所以這一切都很好! (並且沒有錯誤,至少在GZIPInputStream中是

+0

+1擊敗我:-)至少我在JDK中玩得開心:-) – 2011-03-11 18:26:20

+0

實際上我超過了99%肯定當我看到代碼時會發生什麼。 byte [] {0,0,-1,-1}是Z_SYNC_FLUSH的標記,所以他認爲他可能已經命中了它。 – bestsss 2011-03-11 18:28:51

+0

我還沒有使用GZIPInputStream,所以我不得不跟蹤它。我認爲關鍵是腐敗是在拖車而不是數據? – 2011-03-11 18:30:21