技术实践

JavaScript对数据压缩和解压

当文本达到一定长度,且内容中重复的字符出现次数较多,就可以有一个不错的压缩率。通过js实现压缩,发送到后端再实现解压。有效提升同等网络带宽下

羊先生的头像
羊先生2020.10.18 · 2 分钟阅读 · 29 阅读
JavaScript对数据压缩和解压封面
文章正文还需 2 分钟

当文本达到一定长度,且内容中重复的字符出现次数较多,就可以有一个不错的压缩率。通过js实现压缩,发送到后端再实现解压。有效提升同等网络带宽下的传输速率

最近遇到一个项目,传输后端的数据非常大,于是考虑到压缩在进行传输,本次讲解只在客户端压缩

封装压缩和解压缩方法

以下方法来自网络搜索,频率出现高的

压缩

js 复制代码
function Compress(strNormalString) {
    var strCompressedString = "";

    var ht = new Array();
    for(i = 0; i < 128; i++) {
        ht[i] = i;
    }

    var used = 128;
    var intLeftOver = 0;
    var intOutputCode = 0;
    var pcode = 0;
    var ccode = 0;
    var k = 0;

    for(var i=0; i<strNormalString.length; i++) {
        ccode = strNormalString.charCodeAt(i);
        k = (pcode << 8) | ccode;
        if(ht[k] != null) {
            pcode = ht[k];
        } else {
            intLeftOver += 12;
            intOutputCode <<= 12;
            intOutputCode |= pcode;
            pcode = ccode;
            if(intLeftOver >= 16) {
                strCompressedString += String.fromCharCode( intOutputCode >> ( intLeftOver - 16 ) );
                intOutputCode &= (Math.pow(2, (intLeftOver - 16)) - 1);
                intLeftOver -= 16;
            }
            if(used < 4096) {
                used ++;
                ht[k] = used - 1;
            }
        }
    }

    if(pcode != 0) {
        intLeftOver += 12;
        intOutputCode <<= 12;
        intOutputCode |= pcode;
    }

    if(intLeftOver >= 16) {
        strCompressedString += String.fromCharCode( intOutputCode >> ( intLeftOver - 16 ) );
        intOutputCode &= (Math.pow(2,(intLeftOver - 16)) - 1);
        intLeftOver -= 16;
    }

    if( intLeftOver > 0) {
        intOutputCode <<= (16 - intLeftOver);
        strCompressedString += String.fromCharCode( intOutputCode );
    }

    return strCompressedString;
}

解压

js 复制代码
function Decompress(strCompressedString) {
    var strNormalString = "";
    var ht = new Array();

    for(i = 0; i < 128; i++) {
        ht[i] = String.fromCharCode(i);
    }

    var used = 128;
    var intLeftOver = 0;
    var intOutputCode = 0;
    var ccode = 0;
    var pcode = 0;
    var key = 0;

    for(var i=0; i<strCompressedString.length; i++) {
        intLeftOver += 16;
        intOutputCode <<= 16;
        intOutputCode |= strCompressedString.charCodeAt(i);

        while(1) {
            if(intLeftOver >= 12) {
                ccode = intOutputCode >> (intLeftOver - 12);
                if( typeof( key = ht[ccode] ) != "undefined" ) {
                     strNormalString += key;
                    if(used > 128) {
                        ht[ht.length] = ht[pcode] + key.substr(0, 1);
                    }
                     pcode = ccode;
                } else {
                    key = ht[pcode] + ht[pcode].substr(0, 1);
                    strNormalString += key;
                    ht[ht.length] = ht[pcode] + key.substr(0, 1);
                    pcode = ht.length - 1;
                }

                used ++;
                intLeftOver -= 12;
                intOutputCode &= (Math.pow(2,intLeftOver) - 1);
            } else {
                break;
            }
        }
    }
    return strNormalString;
}

使用Pako.js插件

引入CDN

html 复制代码
<script src="https://cdn.staticfile.org/pako/1.0.10/pako.min.js"></script>

NPM

js 复制代码
npm install pako

GitHub

https://github.com/nodeca/pako

演示地址

使用

定义解压和压缩的方法

js 复制代码
function unzip(b64Data){
    var strData   = atob(b64Data);
    // Convert binary string to character-number array
    var charData  = strData.split('').map(function(x){return x.charCodeAt(0);});
    // Turn number array into byte-array
    var binData   = new Uint8Array(charData);
    // // unzip
    var data    = pako.inflate(binData);
    // Convert gunzipped byteArray back to ascii string:
    strData   = String.fromCharCode.apply(null, new Uint16Array(data));
    return decodeURIComponent(strData);
}
function zip(str){
     var binaryString = pako.gzip(encodeURIComponent(str), { to: 'string' })
     return btoa(binaryString);
}

效果,字符串越大,压缩效果越明显

image.png

其他分享

Java 实现Gzip 压缩字符串

Javascript 简单实现Gzip 压缩字符串 基于pako.js