[英]Decompress GZip string in Java
我可以找到很多可以解壓縮GZip文件的函數,但是如何解壓縮GZip字符串呢?
我正在嘗試解析響應主體使用GZip壓縮的HTTP響應。 但是,整個響應只是存儲在一個字符串中,因此字符串的一部分包含二進制字符。
我正在嘗試使用:
byte responseBodyBytes[] = responseBody.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(responseBodyBytes);
GZIPInputStream gzis = new GZIPInputStream(bais);
但這只會引發異常:java.io.IOException:不是GZIP格式
沒有GZip字符串這樣的東西。 GZip是二進制的,字符串是文本。
如果要壓縮字符串,則需要先將其轉換為二進制 - 例如將OutputStreamWriter
鏈接到壓縮OutputStream
(例如GZIPOutputStream
)
同樣地讀取數據,你可以使用一個InputStreamReader
鏈接到一個解壓InputStream
(如GZIPInputStream
)。
從Reader
輕松讀取的一種方法是使用來自Guava的 CharStreams.toString(Readable)
或類似的庫。
理想情況下,您應該使用高級庫來為您處理這些內容。 這樣,無論何時發布新版本的HTTP,圖書館維護者都希望為您完成所有艱苦的工作,您只需要更新版本的庫。
除此之外,嘗試自己做這件事是一個很好的練習。
讓我們假設您正在從TCP套接字讀取HTTP響應作為字節流。 如果沒有gzip編碼,那么將整個響應放入String中就可以了。 但是,“ Content-Encoding:gzip ”標頭的存在意味着響應主體(如您所述)將是二進制的。
您可以將響應正文的開頭標識為第一次出現字符串序列“\\ r \\ n \\ n \\ n \\ n”之后的第一個字節(或4個字節0x0d,0x0a,0x0d,0x0a)。
gzip編碼有一個特殊的頭,你應該測試前3個主體字節:
byte[] buf; // from the HTTP Response stream
// ... insert code here to populate buf from HTTP Response stream
// ...
int bodyLen = 1234; // populate this value from 'Content-length' header
int bodyStart = 123; // index of byte buffer where body starts
if (bodyLen > 4 && buf[bodyStart] == 0x1f && buf[bodyStart + 1] == (byte) 0x8b && buf[bodyStart + 2] == 0x08) {
// gzip compressed body
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
if (bodyStart > 0) bais.skip(bodyStart);
// Decompress the bytes
byte[] decompressedBytes = new byte[bodyLen * 4];
int decompressedDataLength = 0;
try {
// note: replace this try-catch with try-with-resources here where possible
GZIPInputStream gzis = new GZIPInputStream(bais);
decompressedDataLength = gzis.read(decompressedBytes);
gzis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
如果前3個字節與魔術GZIP標頭值不匹配,則GZIPInputStream會產生“Not in GZIP format”錯誤,因此測試這些錯誤將有助於解決您的特定問題。
GZIP格式中還有CRC校驗和,但是如果缺少或不正確,您應該看到不同的錯誤。
可能有幫助:
try (final GZIPInputStream gzipInput = new GZIPInputStream(new ByteArrayInputStream(compressedByteArray));
final StringWriter stringWriter = new StringWriter()) {
org.apache.commons.io.IOUtils.copy(gzipInput, stringWriter, "UTF_8");
String decodedString = stringWriter.toString();
} catch (IOException e) {
throw new UncheckedIOException("Error while decompression!", e);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.