简单说一说Gzip。
我们在进行网络传输数据时,经常用到json、xml等格式的数据,这些数据在传输前可以进行压缩,这时候就会涉及到一种压缩格式—Gzip。Gzip的压缩比率非常大,有的甚至能达到70%以上,可以大大减少传输内容,提高用户的传输速度,进而提高用户的体验。
实际上Gzip的压缩原理,就是对相同内容进行合并归纳,进而减少数据占用的空间。
我们通过百度Gzip压缩检测,可以方便的检查一个网页是否应用了Gzip压缩。我们以开源中国的新闻页为例,网址如下:
http://www.oschina.net/action/api/news_list?catalog=1&pageIndex=0&pageSize=20
检测结果如下:
可以看到,这个网页并未经过压缩,源文件大小为11.53KB,而压缩后,文件可减小到2.67KB,可以节省76.8%的传输控件。这是什么概念呢?相当于100MB的数据经过压缩后变为23MB。(示例中使用的是xml数据,属于文本信息,压缩比率非常高。)
那么,Android能否实现数据的gzip压缩呢?也是可以的。下面,我们就简单讲解一下在Android中实现Gzip压缩的过程。
首先,画图说明一下在Android中实现Gzip压缩的原理:
首先,客户端发请求给服务端,会带上请求头:Accept-Encoding:gzip。第二步,服务端接收到请求头后,可以选择压缩或不压缩。第三步,服务端选择压缩后,文件明显变小,同时在响应头加上Content-Encoding:gzip。第四步,客户端接收到响应后,根据响应头中是否带有Content-Encoding:gzip,判断文件是否被压缩,如果压缩就进行解压,如果没有压缩,就按照正常方式读取数据即可。
接下来是示例代码:
首先是布局,我们简单的设置一个控制Gzip压缩的按钮:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gzip压缩"
android:onClick="gzipRequest" />
</RelativeLayout>
经过检测,百度首页也进行了gzip压缩,所以博主打算以百度首页作为测试网址,检测图如下:
示例的业务逻辑代码如下:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void gzipRequest(View v) {
new Thread() {
public void run() {
try {
gzipRequest();
} catch (Exception e) {
}
};
}.start();
}
protected void gzipRequest() throws Exception {
HttpGet request = new HttpGet("https://www.baidu.com/");
// Accept-Encoding:"gzip, deflate"
// 添加请求头
request.addHeader("Accept-Encoding", "gzip");
HttpClient client = new DefaultHttpClient();
// 发送请求
HttpResponse response = client.execute(request);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity(); // 获取到请求回来的实体
// Content-Encoding:"gzip"
boolean isGzip = false;
Header[] headers = response.getHeaders("Content-Encoding");
for (Header header : headers) {
if ("gzip".equals(header.getValue())) {
isGzip = true;
break;
}
}
System.out.println(isGzip ? "服务器进行了Gzip压缩" : "服务器没有进行Gzip压缩");
String json;
if (isGzip) {
// 解压缩
json = parseGzip(entity);
} else {
// 正常读取
json = EntityUtils.toString(entity, HTTP.UTF_8);
}
System.out.println(json);
}
}
/**
* 解Gzip压缩
*
* @throws IOException
* @throws IllegalStateException
*/
private String parseGzip(HttpEntity entity) throws Exception {
InputStream in = entity.getContent();
GZIPInputStream gzipInputStream = new GZIPInputStream(in);
BufferedReader reader = new BufferedReader(new InputStreamReader(
gzipInputStream, HTTP.UTF_8));
String line = null;
StringBuffer sb = new StringBuffer();
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
}
}
控制台打印结果:
09-08 09:37:03.603: System.out(1655): 服务器进行了Gzip压缩
09-08 09:37:03.603: System.out(1655): <!DOCTYPE html>
09-08 09:37:03.603: System.out(1655): <!--STATUS OK-->
<html>
<head>
<meta http-equiv=content-type content=text/html;charset=utf-8>
<meta http-equiv=X-UA-Compatible content=IE=Edge>
<meta content=always name=referrer>
<link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css>
<title>百度一下,你就知道</title>
</head>
<body link=#0000cc>
<div id=wrapper>
<div id=head>
<div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper>
<div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div>
<form id=form name=f action=//www.baidu.com/s class=fm>
<input type=hidden name=bdorz_come value=1>
<input type=hidden name=ie value=utf-8>
<input type=hidden name=f value=8>
<input type=hidden name=rsv_bp value=1>
<input type=hidden name=rsv_idx value=1>
<input type=hidden name=tn value=baidu>
<span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span>
<span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span>
</form>
</div>
</div>
<div id=u1>
<a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a>
<a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a>
<a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a>
<a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a>
<a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript>
<a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript>
<script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');