浏览 5556 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-09-20
最后修改:2011-09-20
废话不多说!
先上地址和演示
这次发的组件是因为上次遇到一个编码问题而创作的!
众所周知,Js这个东西是老外开发的,所有,他没有内置GBK编码的功能,而在中国,大家都操作系统(windows)默认的codepage就是GBK的,所有呢,当中文出现在URL里面发送的时候,浏览器就会进行一次URLEncode!
而我们平时想将中文在Js中进行GBK编码,那几乎是不可能的!网上的实现,大多数我只能说是纯忽悠吧!鄙视那些漫天转载而不经思考的人!
现在,就有我这个组件来实现纯Js进行GBK编码和解码吧!
当你收到%DA%4D这种GBK编码形式,你可以调用我的decode来实现解码哦! 同样,传入中文 encode('测试中文')将输出 %B2%E2%CA%D4%D6%D0%CE%C4
针对组件的实现,还是很简单的,而简单不代表没有问题,这里的问题比上次提到的省市三级联动组件更加严峻!
因为数据量实在太大了,不过这次的压缩算法的实现确实是解决整个问题的关键! 至于本组件采用了什么压缩算法,先让大家思考下,后期将放出全部完整的原理解析!(组件的源码请查看)
chrome下文件上传不了,郁闷,下载源码请移步组件的源码 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-09-20
LZ果然很闲...
其实你还可以进一步压缩,那一长串数据大部分都是0~f,可以用base64进行编码,1字符表达的数据量分别是4bit和6bit,能压缩33%左右。 P.S. 为什么还要用GBK呢?utf-8就很方便,JS还有内置编码方法:encodeURIComponent/decodeURIComponent。 当然如果是在老系统的基础上做二次开发,那就没办法了。 再P.S. 其实上次你发的那个省市县联动的JS,我也蛋疼了 ,用huffman+base64试着压缩了一下,huffman树占7K左右,base64数据23K,算上代码可能比你的压缩率高点,不过只是尝试下,huffman反序列化没有写。 附上代码,蛋疼的时候可以研究研究: (你的原数据截掉了,太长了,代码写得很随意,将就下吧) (function(){ var str = "北京市:北京市#东城区|西城区|崇文区|宣武区|朝阳区|丰台区|石景山区|海淀区|门头沟区|房山区|通州区*" String.prototype.getACLength = function(){ return encodeURIComponent(this).replace(/%\w\w/g, 'a').length; }; var originalLength = str.getACLength(); // 原始数据字节数 console.log("原始数据大小:" + originalLength); // 计算字频率 var i, map = {}, c; for(i=0; i<str.length; i++){ c = str[i]; map[c] = (map[c] || 0) + 1; } var arr = []; for(c in map){ if(map.hasOwnProperty(c)){ arr.push({ num : map[c], c : c }); } } // 按频率生成huffman树 var Node = function(a, b){ this.left = a; this.right = b; this.num = a.num + b.num; }; var left, right; while(arr.length>1){ arr.sort(function(a, b){ return a.num-b.num; }); left = arr[0]; right = arr[1]; arr.splice(0, 2, new Node(left, right)); } var huffmanTree = arr[0]; // 将huffman树序列化输出(compressTree) + 生成反查字典(字 -> huffman编码) var results = [], compressTree = []; function output(node, base){ base = base || ""; if(node instanceof Node){ compressTree.push(":"); output(node.left, base + "0"); compressTree.push(","); output(node.right, base + "1"); }else{ compressTree.push(node.c.charCodeAt(0).toString(36)); results.push({ code : base, c : node.c }); } } output(huffmanTree); compressTree = compressTree.join(""); results.sort(function(a, b){ var len = a.code.length - b.code.length; if(len === 0){ return a.code - b.code; } return len; }); // 反查字典 var strs = [], result, dictMap = {}; for(i=0; i<results.length; i++){ result = results[i]; strs.push(result.code + " : " + result.c); dictMap[result.c] = result.code; } var huffmanTreeLength = compressTree.getACLength(); console.log("huffman树数据大小:" + huffmanTreeLength); //console.log(compressTree); //console.log(strs.join("\n")); // huffman编码处理 function encode(str, dictMap){ return str.replace(/./g, function(c){ return dictMap[c]; }); } // 生成base64字典 var base64Map = {}, reverseBase64Map = {}, key, value, base64List = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; for(i=0; i<64; i++){ key = i.toString(2); if(key.length<6){ key = "000000".slice(key.length) + key; } base64Map[key] = base64List[i]; reverseBase64Map[base64List[i]] = key; } // base64编码处理 function toBase64(str){ if(str.length%24 !== 0){ // 补全24位整数 str = str + "000000000000000000000000".slice(str.length%24); } return str.replace(/[01]{6}/g, function(key){ return base64Map[key]; }); } // base64解码处理 function fromBase64(str){ return str.replace(/./g, function(c){ return reverseBase64Map[c]; }); } var encodedStr = encode(str, dictMap); var huffmanLength = encodedStr.getACLength(); var base64Str = toBase64(encodedStr); var base64Length = base64Str.getACLength(); console.log("huffman+base64编码最终大小:" + base64Length); console.log("压缩率:" + ( (huffmanTreeLength + base64Length) / originalLength * 100 ).toFixed(2) + "%" ); //console.log(base64Str, base64Str.length); // huffman解码处理 function decode(str, huffmanTree){ var node = huffmanTree, plain = [], c, pos = 0, b; while(pos < str.length){ b = str.charAt(pos); if(b==="0"){ node = node.left; }else{ node = node.right; } if(node.c){ plain.push(node.c); node = huffmanTree; } pos++; } plain = plain.join(""); var lastAvalibleIndex = plain.lastIndexOf("*"); return plain.slice(0, lastAvalibleIndex+1); } console.log("验证解码:" + (decode(fromBase64(base64Str), huffmanTree) === str ? "成功" : "失败") ); //console.log(decode(fromBase64(base64Str), huffmanTree)) })(); 实际数据输出结果 引用 原始数据大小:51862 huffman树数据大小:7001 huffman+base64编码最终大小:23344 压缩率:58.51% 验证解码:成功 |
|
返回顶楼 | |
发表时间:2012-05-29
最后修改:2012-05-29
楼主绝对是闲得蛋疼!!!
我写一个支持GBK的URLEncode和URLDecode只要不到1K的代码你信不??? 给你看个示例代码吧! var iframe=document.createElement("iframe"); iframe.src="about:blank"; iframe.setAttribute("style","display:none;visibility:hidden;"); document.body.appendChild(iframe); var d=iframe.contentWindow.document; d.charset=d.characterSet="GBK"; function getGBKEscape(s) { d.write("<body><a href='?"+s+"'>X</a></body>"); d.close(); var url=d.body.firstChild.href; return url.substr(url.lastIndexOf("?")+1); } 看明白木有啊?哪需要什么把所有GBK字全写到JS中哪 http://www.jamcode.org/ |
|
返回顶楼 | |