如何检查输入流是否被Gz压缩?

有没有办法检查输入流是否已被gz压缩?代码如下:

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;

}

答案 1

它不是万无一失的,但它可能是最简单的,并且不依赖于任何外部数据。像所有体面的格式一样,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;
}

(幻数来源:GZip文件格式规范)

更新:我刚刚发现还有一个包含此值的常量,因此,如果您真的想要,可以使用它的较低两个字节。GZIP_MAGICGZipInputStream


答案 2

InputStream 来自 HttpURLConnection#getInputStream()

在这种情况下,您需要检查 HTTP 响应标头是否等于 。Content-Encodinggzip

URLConnection connection = url.openConnection();
InputStream input = connection.getInputStream();

if ("gzip".equals(connection.getContentEncoding())) {
    input = new GZIPInputStream(input);
}

// ...

这一切都在HTTP规范中明确指定。


更新:按照您如何压缩流源的方式:此比率检查非常漂亮...疯。摆脱它。相同的长度并不一定意味着字节是相同的。让它始终返回gziped流,以便您始终可以期待gziped流,并且无需进行令人讨厌的检查即可应用。GZIPInputStream


推荐