问题描述: 今天遇到个奇怪的bug:java.io.IOException: Not in GZIP format
源码呈现:
package com.beyond.hibernate.common;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* @SystemName:压缩、解压缩工具类
* @author ZX
* @version V1.0
* @Description: 将一传来的字串按照zip方式压缩和解压缩
*/
public class ZIPUtil {
/**
* @Title: compressByte
* @author ZX
* @param param
* @return byte[]
* @throws IOException
*/
public static byte[] compressByte(String param) throws IOException {
if (param == null || param.length() == 0) {
return null;
}
ByteArrayOutputStream byteOut = null;
GZIPOutputStream gzipOut = null;
byte[] outPut = null;
try {
// 开启数据输出流,关闭无效
byteOut = new ByteArrayOutputStream();
// 开启数据压缩流
gzipOut = new GZIPOutputStream(byteOut);
// 将字串转换成字节,然后按照UTF-8的形式压缩
gzipOut.write(param.getBytes("UTF-8"));
// 压缩完毕
gzipOut.finish();
gzipOut.close();
// 将压缩好的流转换到byte数组中去
outPut = byteOut.toByteArray();
byteOut.flush();
byteOut.close();
} finally {
if (byteOut != null) {
byteOut.close();
}
}
return outPut;
}
/**
* @Title: uncompressByte
* @author ZX
* @param param
* @return byte[]
* @throws IOException
*/
public static String uncompressByte(byte[] param) throws IOException {
ByteArrayOutputStream out = null;
ByteArrayInputStream in = null;
GZIPInputStream gzip = null;
byte[] b = null;
try {
// 创建输出流
out = new ByteArrayOutputStream();
// 创建输入流,并把传入的字串参数转码成ISO-8895-1
in = new ByteArrayInputStream(param);
// 创建压缩输入流,将大小默认为参数输入流大小
gzip = new GZIPInputStream(in);
// 创建byte数组用于接收解压后的流转化成byte数组
byte[] byteArry = new byte[256];
int n = -1;
while ((n = gzip.read(byteArry)) != -1) {
out.write(byteArry, 0, n);
}
// 转换数据
b = out.toByteArray();
out.flush();
} finally {
// 关闭压缩流资源
if(out != null)
out.close();
if(gzip != null)
gzip.close();
if(in != null)
in.close();
}
return new String(b,"UTF-8");
}
public static void main(String[] args) {
String param = "beyond ,come on ,you can do it !";
String str = "", st = "";
try {
str = new String(ZIPUtil.compressByte(param));
st = new String(ZIPUtil.uncompressByte(param.getBytes()));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(str);
System.out.println("=======================");
System.out.println(st);
}
}
bug描述:
java.io.IOException: Not in GZIP format
at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:141)
at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:56)
at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:65)
at com.beyond.hibernate.common.ZIPUtil.uncompressByte(ZIPUtil.java:73)
at com.beyond.hibernate.common.ZIPUtil.main(ZIPUtil.java:122)
延迟解决原因:延迟处理。。。不知道怎么解决,发现这个bug应该和IO流底层有关
bug原因:是 st = new String(ZIPUtil.uncompressByte(param.getBytes()));调用时有问题,其中param.getBytes()在api中说是转换成的byte数组,但是这和uncompressByte(byte[])方法所要的参数byte[] 还不太一样,归根结底我认为是String中的Bytes()方法得到的byte[]和GZIPInputStream 所要的byte[] 不一样的,但是至于为何不一样?
这是由于String中的Bytes()方法得到的byte[]数组,而GZIPInputStream 所要的byte[]是一个流,为何这么说?如下:可以看出来这里的b是ByteArrayOutputStream流的toByteArray()方法得到的,里面的内容是流数据,而String中的Bytes()方法得到的byte[]内容是使用平台的默认字符集将此String
编码为 byte 序列,也就是编码后的字串内容成的byte[] 数组,经过 in = new ByteArrayInputStream(param);处理后成为流但是在 gzip = new GZIPInputStream(in);这一步就出错了,报错说是格式不对。。。到现在还没搞清楚是啥问题。。。。
临时解决方案:将结果单独列出来,其中写一句byte[] b = ZIPUtil.compressByte(param); 然后将b 传给ZIPUtil.uncompressByte(b); 数据结果是对的。
总结:byte[] 和 String方法getBytes() 在某些条件下是不能等同的