voo*_*voo 51 java gzip http inputstream httpurlconnection
有没有办法检查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;
}
}
Run Code Online (Sandbox Code Playgroud)
我试过这种方式,但它没有按预期工作 - 从流中读取的值无效.编辑:添加了我用来压缩数据的方法:
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;
}
Run Code Online (Sandbox Code Playgroud)
biz*_*lop 64
它并非万无一失,但它可能是最简单的,不依赖于任何外部数据.像所有体面的格式一样,GZip也以一个神奇的数字开头,可以在不读取整个流的情况下快速检查.
public static InputStream decompressStream(InputStream input) {
PushbackInputStream pb = new PushbackInputStream( input, 2 ); //we need a pushbackstream to look ahead
byte [] signature = new byte[2];
int len = pb.read( signature ); //read the signature
pb.unread( signature, 0, len ); //push back the signature to the stream
if( signature[ 0 ] == (byte) 0x1f && signature[ 1 ] == (byte) 0x8b ) //check if matches standard gzip magic number
return new GZIPInputStream( pb );
else
return pb;
}
Run Code Online (Sandbox Code Playgroud)
(幻数的来源:GZip文件格式规范)
更新:我刚刚dicovered这里面还有一个叫常GZIP_MAGIC
在GZipInputStream
其中包含这个值,所以如果你真的想,你可以使用它的两个低字节.
Bal*_*usC 40
InputStream来自HttpURLConnection#getInputStream()
在这种情况下,您需要检查HTTP Content-Encoding
响应标头是否等于gzip
.
URLConnection connection = url.openConnection();
InputStream input = connection.getInputStream();
if ("gzip".equals(connection.getContentEncoding())) {
input = new GZIPInputStream(input);
}
// ...
Run Code Online (Sandbox Code Playgroud)
这一切都在HTTP规范中明确规定.
更新:按照压缩源流的方式:这个比率检查非常......疯狂.摆脱它.相同的长度并不一定意味着字节是相同的.让它总是返回gzip流,这样你就可以一直期望一个gzip流,只需应用GZIPInputStream
而不需要讨厌的检查.
Aar*_*ler 24
我发现这个有用的例子提供了一个干净的实现isCompressed()
:
/*
* Determines if a byte array is compressed. The java.util.zip GZip
* implementaiton does not expose the GZip header so it is difficult to determine
* if a string is compressed.
*
* @param bytes an array of bytes
* @return true if the array is compressed or false otherwise
* @throws java.io.IOException if the byte array couldn't be read
*/
public boolean isCompressed(byte[] bytes) throws IOException
{
if ((bytes == null) || (bytes.length < 2))
{
return false;
}
else
{
return ((bytes[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (bytes[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)));
}
}
Run Code Online (Sandbox Code Playgroud)
我成功测试了它:
@Test
public void testIsCompressed() {
assertFalse(util.isCompressed(originalBytes));
assertTrue(util.isCompressed(compressed));
}
Run Code Online (Sandbox Code Playgroud)
小智 8
我相信这是检查字节数组是否是gzip格式化的最简单方法,它不依赖于任何HTTP实体或mime类型支持
public static boolean isGzipStream(byte[] bytes) {
int head = ((int) bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
return (GZIPInputStream.GZIP_MAGIC == head);
}
Run Code Online (Sandbox Code Playgroud)
基于@biziclop 的答案 - 该版本使用 GZIP_MAGIC 标头,并且对于空或单字节数据流也是安全的。
public static InputStream maybeDecompress(InputStream input) {
final PushbackInputStream pb = new PushbackInputStream(input, 2);
int header = pb.read();
if(header == -1) {
return pb;
}
int b = pb.read();
if(b == -1) {
pb.unread(header);
return pb;
}
pb.unread(new byte[]{(byte)header, (byte)b});
header = (b << 8) | header;
if(header == GZIPInputStream.GZIP_MAGIC) {
return new GZIPInputStream(pb);
} else {
return pb;
}
}
Run Code Online (Sandbox Code Playgroud)
将原始流包装在 BufferedInputStream 中,然后将其包装在 GZipInputStream 中。接下来尝试提取 ZipEntry。如果有效,则它是一个 zip 文件。然后,您可以在检查后在 BufferedInputStream 中使用“mark”和“reset”返回到流中的初始位置。
归档时间: |
|
查看次数: |
42996 次 |
最近记录: |