解压GZIP压缩数组前,如何获取原数组长度以申请适配缓冲区?
获取GZIP压缩字节数组的原始长度,精准适配缓冲区大小
嘿,我来帮你搞定这个问题!要在解压GZIP压缩字节数组前拿到原始数据的长度,其实不用费劲先解压——GZIP格式本身就在压缩数据的末尾藏了这个信息,咱们直接解析出来就行,这样就能精准申请适配大小的缓冲区了。
原理说明
GZIP格式的尾部有固定结构:最后4个字节是原始未压缩数据的长度(以32位无符号整数存储,采用小端字节序),再往前4个字节是CRC32校验值。我们只需要读取这最后4个字节,转换成整数就能得到原始数据的长度。
具体实现代码
先解析原始长度,再用这个长度初始化缓冲区和输出流,完整代码如下:
byte[] localByteBuf = ...; // 你的GZIP压缩字节数组 int originalLength = 0; // 解析GZIP尾部的原始长度字段 if (localByteBuf.length >= 4) { // 小端字节序转整数:最后一个字节是最低位,依次左移拼接 originalLength = ((localByteBuf[localByteBuf.length - 4] & 0xFF) << 24) | ((localByteBuf[localByteBuf.length - 3] & 0xFF) << 16) | ((localByteBuf[localByteBuf.length - 2] & 0xFF) << 8) | (localByteBuf[localByteBuf.length - 1] & 0xFF); } // 用解析到的长度初始化缓冲区,兜底默认值1024(防止数据不完整的情况) byte[] buffer = new byte[originalLength > 0 ? originalLength : 1024]; ByteArrayOutputStream out = new ByteArrayOutputStream(originalLength > 0 ? originalLength : 1024); try (ByteArrayInputStream bin = new ByteArrayInputStream(localByteBuf); GZIPInputStream gis = new GZIPInputStream(bin)) { int len; while ((len = gis.read(buffer)) > 0) { out.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } // 最终解压后的数据可以通过out.toByteArray()获取
注意事项
- 局限性:如果原始数据长度超过4GB(2^32字节),32位的长度字段会溢出,无法正确获取长度。不过绝大多数业务场景都不会遇到这种极端情况。
- 合法性校验:如果
localByteBuf的长度小于4,说明这不是合法的GZIP数据或者数据不完整,这时候我们用默认的1024作为兜底,也可以根据业务需求抛出异常提示。
内容的提问来源于stack exchange,提问作者eahau
相关产品推荐
相关产品推荐

