【发布时间】:2011-06-16 15:36:35
【问题描述】:
有什么方法可以检查 InputStream 是否已被 gzip 压缩? 代码如下:
public static InputStream decompressStream(InputStream input) {
try {
GZIPInputStream gs = new GZIPInputStream(input);
return gs;
} catch (IOException e) {
logger.info("Input stream not in the GZIP format, using standard format");
return input;
}
}
我尝试过这种方式,但它没有按预期工作 - 从流中读取的值无效。 编辑: 添加了我用来压缩数据的方法:
public static byte[] compress(byte[] content) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
GZIPOutputStream gs = new GZIPOutputStream(baos);
gs.write(content);
gs.close();
} catch (IOException e) {
logger.error("Fatal error occured while compressing data");
throw new RuntimeException(e);
}
double ratio = (1.0f * content.length / baos.size());
if (ratio > 1) {
logger.info("Compression ratio equals " + ratio);
return baos.toByteArray();
}
logger.info("Compression not needed");
return content;
}
【问题讨论】:
-
InputStream来自哪里?来自URLConnection#getInputStream()?在像 HTTP 这样有点体面的协议中,应该已经以某种方式指示最终用户内容已被压缩。 -
鉴于 GZIP 具有 32 位 CRC,我觉得这很令人惊讶。一个损坏的流至少应该在最后抛出一个异常。
-
我想知道 OP 是否意味着在 IOException 发生后从流中读取的值无效......这是有道理的,因为 GZIPInputStream 构造函数会消耗流中的一些字节.
-
值在 IOException 发生后损坏。 InputStream 来自 HttpURLConnection#getInputStream()
-
所以一般的解决方案是创建一个 BufferedInputStream 包装原始输入流,然后调用“mark”来标记流的开始。然后围绕它包装一个 GZipInputStream 。如果没有异常,返回 GZipInputStream。如果发生异常,调用“reset”并返回BufferedInputStream。
标签: java http gzip inputstream httpurlconnection