How to check if InputStream is Gzipped?
Solution 1:
It's not foolproof but it's probably the easiest and doesn't rely on any external data. Like all decent formats, GZip too begins with a magic number which can be quickly checked without reading the entire stream.
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;
}
(Source for the magic number: GZip file format specification)
Update: I've just dicovered that there is also a constant called GZIP_MAGIC
in GZipInputStream
which contains this value, so if you really want to, you can use the lower two bytes of it.
Solution 2:
The InputStream comes from HttpURLConnection#getInputStream()
In that case you need to check if HTTP Content-Encoding
response header equals to gzip
.
URLConnection connection = url.openConnection();
InputStream input = connection.getInputStream();
if ("gzip".equals(connection.getContentEncoding())) {
input = new GZIPInputStream(input);
}
// ...
This all is clearly specified in HTTP spec.
Update: as per the way how you compressed the source of the stream: this ratio check is pretty... insane. Get rid of it. The same length does not necessarily mean that the bytes are the same. Let it always return the gzipped stream so that you can always expect a gzipped stream and just apply GZIPInputStream
without nasty checks.