本文数据有误,导致压缩效果结论严重偏离事实,正确的情况是,即使用DEFLATE压缩,和GZIP压缩效果相差无几,因为它们本来都是从哈夫曼编码中分支出来的。。。如果你还想了解下传输优化,可以搜索下 MessagePack 也许可以帮到你~
首先,先想想我们异步传输的数据是什么,图片or文字?如果是图片视频类,sorry,下面内容不用看了,帮不了你。这里我们讨论的情况是传输文本,文字的情况(我相信99%的异步都是处理这方面的事情)。
OK,先说说原理。为什么图片和视频类优化不了呢,原因就是,这些东东已经是2进制的了,而我们平常看的文本则是10进制的。如果我们在传输之前,把文本转为2进制压缩,在客户端接收到数据后再做2进制转10进制的解压缩,就可以大大的减少异步传输的数据量。我这里的测试结果是673KB的数据,经过2进制压缩,以及兼容性处理后,大小变为18KB,整整减少了99.97%的数据传输量。可以说,大大的降低了客户加载数据时间,客户体验上了几个层次。。
单纯的转为二进制是不行D, 要把二进制进行压缩才能达到超级无敌的压缩效果。。这里偶尔陶醉我是使用PHP作为服务端的,客户端是使用FLEX。幸运的是,强大的PHP已经把这种压缩算法—deflate 内置到了PHP当中,在PHP中可以直接使用gzdeflate进行压缩,gzinflate进行解压缩。
什么是DEFLATE?
DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。它最初是由Phil Katz为他的PKZIP归档工具第二版所定义的,后来定义在RFC 1951规范中。
人们普遍认为DEFLATE不受任何专利所制约,并且在LZW(GIF文件格式使用)相关的专利失效之前,这种格式除了在ZIP文件格式中得到应用之外也在gzip压缩文件以及PNG图像文件中得到了应用。
DEFLATE压缩与解压的源代码可以在自由、通用的压缩库zlib上找到。
这是一个开源算法,应该会有什么版本都有的,其他语言都有这个内置算。客户端的话,我使用的FLEX也有这个算法包,只要import flash.utils.ByteArray; 就可以使用ByteArray对象调用inflate()函数进行解压。
我相信看到这篇文章的都是程序猿多,说再多也没用,还不如直接贴源码。。。哈哈,最后附上源码。当然,只是一个简单的demo,方便大家理解而已。先讲解下,这个demo是模拟FLEX调用PHP的接口,PHP模拟压缩返回大量数据,FLEX接送到数据后做解压处理,然后画图(K线图)。
)。
代码如下 | 复制代码 |
<?php $file = ‘c:/test.txt’; $content = file_get_contents($file); //file_put_contents(‘c:/1.txt’,base64_encode(gzdeflate($content,6))); header(“Content-Length:”.strlen( base64_encode(gzdeflate($content)) )); echo base64_encode(gzdeflate($content)); ?> |
以下是flex的代码,模拟股票K线图,需要调用大量数据。
代码如下 | 复制代码 |
<?xml version=“1.0″ encoding=“utf-8″?> <s:Application xmlns:fx=“http://ns.adobe.com/mxml/2009″ xmlns:s=“library://ns.adobe.com/flex/spark” xmlns:mx=“library://ns.adobe.com/flex/mx” minWidth=“955″ minHeight=“600″ creationComplete=“init()”> <fx:Declarations> <mx:HTTPService id=“srv” resultFormat=“text” useProxy=“false” result=“resultDatas(event)” />
<!– K线图 上涨下跌2种样式 –> <mx:SolidColor id=“up” color=“red” alpha=“.8″/> <mx:SolidColor id=“down” color=“green” alpha=“.8″/>
<!– 一些线 –> <mx:SolidColorStroke id=“line_ma5″ color=“#ff8040″ weight=“0.5″ alpha=“1″/> <mx:SolidColorStroke id=“line_ma10″ color=“#60A2FF” weight=“0.5″/> <mx:SolidColorStroke id=“line_ma20″ color=“#ff00ff” weight=“0.5″/> <mx:SolidColorStroke id=“line_ma30″ color=“#008000″ weight=“0.5″/> <!– 将非可视元素(例如服务、值对象)放在此处 –> </fx:Declarations> <fx:Script> <![CDATA[ /* * deflate.mxml * 作者:偶尔陶醉 blog:www.stutostu.com * 功能: 模拟股票K线图,向PHP接口调用大量数据 */ import flash.utils.ByteArray;
import mx.collections.ArrayCollection; import mx.controls.Alert; import mx.controls.Label; import mx.rpc.events.ResultEvent; import mx.utils.Base64Decoder;
import spark.components.TextArea;
private var str:String; [Bindable] private var _myData:ArrayCollection; private var big:ArrayCollection; private var page:int=1; private var allpage:int; private var start:int = 0; private function init():void{ this.systemManager.stage.addEventListener(KeyboardEvent.KEY_DOWN ,_keyDownHandler); srv.url = “http://localhost/test.php”; srv.send();
}
private function resultDatas(event:ResultEvent):void{ str = event.result.toString(); var base64:Base64Decoder = new Base64Decoder(); base64.decode( str ); var byte:ByteArray = new ByteArray(); byte = base64.toByteArray(); byte.inflate(); var result:String = byte.toString();
var words:Array=result.split(‘;’); var subwords:Array=[]; allpage = words.length-1; var max:Number=1; var min:Number=100000; big = new ArrayCollection();
Alert.show(“ooxx”); for(var i:int = 0;i <= allpage;i++) { subwords=words[i].split(‘,’); subwords[0] = subwords[0].substr(0,10); big.addItem({“Date”: subwords[0], “Open”: Number(subwords[1]), “High”:Number(subwords[2]), “Low”:Number(subwords[3]),”Close”:Number(subwords[4]),”Vol”:Number(subwords[5]), “Amount”:subwords[6],”VMa5″:subwords[7],”VMa10″:subwords[8],”VMa20″:subwords[9], “Ma5″:subwords[10],”Ma10″:subwords[11],”Ma20″:subwords[12],”Ma30″:subwords[13], “K”:subwords[14],”D”:subwords[15],”J”:subwords[16],”Diff”:subwords[17], “Dea”:subwords[18],”Macd”:subwords[19]}); }
extrude();
}
public function extrude():void{ page <= 0 ? page = 1 : ”; var end:int = page*30; _myData = new ArrayCollection(); for(var i:int=0;i<=end;i++) { _myData.addItem( {“Date”: big[i]['Date'], “Open”: big[i]['Open'], “High”:big[i]['High'], “Low”:big[i]['Low'],”Close”:big[i]['Close'],”Vol”:big[i]['Vol'], “Amount”:big[i]['Amount'] } ); } }
protected function _keyDownHandler(event:KeyboardEvent):void{ switch(event.keyCode) { case 38: page–; extrude(); break; case 40: page++; extrude(); break; } }
]]> </fx:Script> <mx:CandlestickChart id=“candlestickchart” width=“100%” height=“70%” chromeColor=“#040404″ color=“#FFFFFF” dataProvider=“{_myData}” paddingLeft=“2″ showDataTips=“false” textAlign=“right” > <mx:verticalAxis> <mx:LinearAxis id=“vaxis” baseAtZero=“false” /> </mx:verticalAxis>
<mx:verticalAxisRenderers> <mx:AxisRenderer axis=“{vaxis}” placement=“left” labelGap=“0″ > <mx:axisStroke> <mx:SolidColorStroke color=“#CCCCCC” weight=“1″ alpha=“0.8″ /> </mx:axisStroke> </mx:AxisRenderer> </mx:verticalAxisRenderers>
<mx:horizontalAxis> <mx:CategoryAxis id=“haxis” categoryField=“Date” /> </mx:horizontalAxis>
<mx:horizontalAxisRenderers> <mx:AxisRenderer axis=“{haxis}” canDropLabels=“true”> <mx:axisStroke> <mx:SolidColorStroke color=“#bbccdd” weight=“1″ alpha=“0.8″/> </mx:axisStroke> </mx:AxisRenderer> </mx:horizontalAxisRenderers> <mx:series> <mx:CandlestickSeries id=“main_line” openField=“Open” highField=“High” lowField=“Low” closeField=“Close” fill=“{up}” declineFill=“{down}” /> <mx:LineSeries yField=“Ma5″ lineStroke=“{line_ma5}”/> <mx:LineSeries yField=“Ma10″ lineStroke=“{line_ma10}”/> <mx:LineSeries yField=“Ma20″ lineStroke=“{line_ma20}”/> <mx:LineSeries yField=“Ma30″ lineStroke=“{line_ma30}”/> </mx:series> </mx:CandlestickChart> </s:Application> |
哈哈,很简单的demo,希望能帮到你理解我在说什么。。。如果能帮到你,记得留言一下支持我哦。。。你也可以把这文章通过分享按钮分享给你朋友。。。
最后附上测试数据,也就是PHP中调用的test.txt 这个数据一共600多KB,测试一下吧,你会发现,压缩,真的很牛。。。
test.txt(右键另存为即可)
——————–bug修复——更新时间:2012/4/12 10:29———————-
在常规兼容性测试时,发现chrome返回压缩数据有问题。经查明,原因在于Transfer-Encoding:chunked 。 chrome 浏览器采用的是严格chunked协议,没有收到明确的chunked结束符会导致出错。所以只要在php输出数据前,用header设置一下Content-Length 告诉浏览器,返回的数据长度,就可避免这种情况发生。