使用GZIP进行数据压缩传输实验,服务端是J2EE,使用HTTP的POST方式进行数据请求。
为了方便测试,刚开始在J2EE的环境下写了一个TestCase去调用J2EE写的服务,忘记写GZIP解压代码,数据居然能够正常解压。
好!因为服务是最终提供给android端来调用的,所以改换成android客户端来测试。
刚开始没有显式调用GZIP解压,发现数据死活显示不正确,截获到的数据如下:
??V*J-v?O?T?RR?q??SR?? ?l??t???募??c???J?@B??2
接下来尝试使用下面的代码进行解压,结果就出来了。
{"resBody":"","resCode":1,"resMsg":"解析成功"}
在这个过程中,发现一个很奇怪的特点。
果断设置断点对请求的报头进行分析,发现在J2EE环境下调用,竟然可以不用显式调用解压代码,apache的http包居然会根据response的报头是否GZIP,自动调用一个GZIP***Stream的类进行解压。
反观android端,即便接收到的是GZIP数据,但调用的是EOF****Stream类去转InputStream,输出的结果是没有解压的数据。
尼玛,J2EE怎么这么懂人意呀?!看来惯性思维不管用呀!
android解压代码:
1 /** 2 * @Title: getJsonStringFromGZIP 3 * @Description: GZIP解压缩,转成JSON字符串 4 * @param response 5 * @return String 返回类型 6 * @throws 7 */ 8 public static String getJsonStringFromGZIP(HttpResponse response) { 9 String jsonString = null; 10 try { 11 InputStream is = response.getEntity().getContent(); 12 BufferedInputStream bis = new BufferedInputStream(is); 13 bis.mark(2); 14 // 取前两个字节 15 byte[] header = new byte[2]; 16 int result = bis.read(header); 17 // reset输入流到开始位置 18 bis.reset(); 19 // 判断是否是GZIP格式 20 int headerData = getShort(header); 21 // Gzip 流 的前两个字节是 0x1f8b 22 if (result != -1 && headerData == 0x1f8b) { 23 is = new GZIPInputStream(bis); 24 } else { 25 is = bis; 26 } 27 InputStreamReader reader = new InputStreamReader(is, "utf-8"); 28 char[] data = new char[100]; 29 int readSize; 30 StringBuffer sb = new StringBuffer(); 31 while ((readSize = reader.read(data)) > 0) { 32 sb.append(data, 0, readSize); 33 } 34 jsonString = sb.toString(); 35 bis.close(); 36 reader.close(); 37 } catch (Exception e) { 38 throw new DataException(e); 39 } 40 41 return jsonString; 42 }
android的http请求报头需加上以下代码:
1 httpRequest.setHeader("Accept-Encoding", "gzip"); httpRequest.setHeader("Accept", "application/octet-stream");
PS, 据说现在可以做成服务端配置,无论服务端还是客户端,都无需显式调用GZIP加解压。有时间得试一试!
原文:http://www.cnblogs.com/jaenson/p/4273300.html