TS/JS 使用pako.js 壓縮字符串和二進(jìn)制

因?yàn)轫?xiàng)目需要壓縮字符串和二進(jìn)制感帅,找到了pako這個(gè)庫(kù):
https://github.com/nodeca/pako
https://gitee.com/renew_old_romance/pako/tree/master
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/pako/index.d.ts

一绷柒、簡(jiǎn)單介紹

參考Javascript 簡(jiǎn)單實(shí)現(xiàn)Gzip 壓縮字符串 基于pako.js

<script>
    function input() {
        const input = document.getElementById('input').value;
        const ys = zip(input);
        const jy = unzip(ys);
        document.getElementById('yw').innerText = input;
        document.getElementById('ys').innerText = ys;
        document.getElementById('jy').innerText = jy;
        document.getElementById('ysl').innerText = 
        (Math.round(length(ys) / length(input) * 10000) / 100.00 + "%");

    }

    // 解壓
    function unzip(b64Data) {
        let strData = atob(b64Data);
        const charData = strData.split('').map(function (x) {
            return x.charCodeAt(0);
        });
        const binData = new Uint8Array(charData);
        const data = pako.inflate(binData);
        strData = String.fromCharCode.apply(null, new Uint16Array(data));
        return decodeURIComponent(strData);
    }

    // 壓縮
    function zip(str) {
        const binaryString = pako.gzip(encodeURIComponent(str), {to: 'string'})
        return btoa(binaryString);
    }

    // 占用字節(jié)數(shù)計(jì)算(UTF-8)
    function length(str) {
        let total = 0, charCode, i, len;
        for (i = 0, len = str.length; i < len; i++) {
            charCode = str.charCodeAt(i);
            if (charCode <= 0x007f) {
                total += 1;
            } else if (charCode <= 0x07ff) {
                total += 2;
            } else if (charCode <= 0xffff) {
                total += 3;
            } else {
                total += 4;
            }
        }
        return total;
    }
</script>
二、二進(jìn)制壓縮/解壓縮
    //壓縮
    public static deflatePlan(b: model_a.Byte): Uint8Array {
        return pako.deflate(new Uint8Array(b.buffer));
    }

    //解壓
    public static inflatePlan(b: Uint8Array): Uint8Array {
        return pako.inflate(b);
    }
1.壓縮后存儲(chǔ)成本地文件
let e = PlanTool.encodePlan(data);
console.log("編碼數(shù)據(jù):", e);

let d = PlanTool.decodePlan(e);
console.log("畫墻方案編碼然后解碼:", d);
//壓縮后存儲(chǔ)
let plan = PlanTool.deflatePlan(e);
PlanTool.saveForWebBrowser(new Blob([plan.buffer]), "plan");

//---------------------------------------------
// let str = JSON.stringify(obj);
// let b = new Blob([str]);
public static saveForWebBrowser(b: Blob, fileName: string) {
    let downloadLink = document.createElement('a');
    downloadLink.download = fileName;
    downloadLink.innerHTML = 'Download File';
    if (window.URL != null) {
        downloadLink.href = window.URL.createObjectURL(b);
    } else {
        downloadLink.href = window.URL.createObjectURL(b);
        downloadLink.onclick = () => {
            document.body.removeChild(downloadLink);
        };
        downloadLink.style.display = 'none';
        document.body.appendChild(downloadLink);
    }
    downloadLink.click();
}
2.加載本地文件后夺饲,解壓縮
//https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
let oReq = new XMLHttpRequest();
oReq.open("GET", "resources/plan.txt", true);
oReq.responseType = "arraybuffer";
oReq.onload = () => {
    let arrayBuffer = oReq.response as ArrayBuffer; // 注意:不是oReq.responseText
    if (arrayBuffer) {
        //解壓
        let byteArray = new Uint8Array(arrayBuffer);
        let d = PlanTool.inflatePlan(byteArray);
        //解碼
        let b = new model_a.Byte(d.buffer);
        let decodeData = PlanTool.decodePlan(b);
        console.log("畫墻方案編碼然后解碼:", decodeData);

        let scene = Eventtower.instance.getAtt(TGetGloba.GET_STAGE_MANAGER).scene;
        let idToContent = Eventtower.instance.getAtt(TGetGloba.GET_STAGE_MANAGER).idToContent;
        scene.decodeToObject(decodeData, idToContent);
        //性能測(cè)試
        PlanTool.benchmarkDecodePlan(b);
        PlanTool.benchmarkInflatePlan(byteArray);
    }
};
oReq.send(null);
三、字符串壓縮/解壓縮
private 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:
  return this.ab2str(data);
}

private zip(str) {
  var binaryString = pako.gzip(str, { to: 'string' });
  let v = this.ab2str(binaryString as any);
  return btoa(v);
}

// ArrayBuffer轉(zhuǎn)為字符串施符,參數(shù)為ArrayBuffer對(duì)象
private ab2str(buf: ArrayBuffer): string {
  var binaryString = '';
  let bytes = new Uint16Array(buf);
  let length = bytes.length;
  for (var i = 0; i < length; i++) {
    binaryString += String.fromCharCode(bytes[i]);
  }
  return binaryString;
}

因?yàn)樽址枰c后端通訊往声,所以使用了bota/atob進(jìn)行base64編碼。

1.ArrayBuffer轉(zhuǎn)為字符串的問(wèn)題

關(guān)于字符串與二進(jìn)制處理戳吝,可以參考jsmpeg系列一 基礎(chǔ)知識(shí) 字符處理 ArrayBuffer TypedArray浩销,其中提到了ArrayBuffer與字符串的互相轉(zhuǎn)換。

ArrayBuffer轉(zhuǎn)為字符串听哭,或者字符串轉(zhuǎn)為ArrayBuffer慢洋,有一個(gè)前提,即字符串的編碼方法是確定的陆盘。假定字符串采用UTF-16編碼(JavaScript的內(nèi)部編碼方式)普筹,可以自己編寫轉(zhuǎn)換函數(shù)。

// ArrayBuffer轉(zhuǎn)為字符串隘马,參數(shù)為ArrayBuffer對(duì)象
function ab2str(buf) {
   return String.fromCharCode.apply(null, new Uint16Array(buf));
}

// 字符串轉(zhuǎn)為ArrayBuffer對(duì)象太防,參數(shù)為字符串
function str2ab(str) {
    var buf = new ArrayBuffer(str.length*2); // 每個(gè)字符占用2個(gè)字節(jié)
    var bufView = new Uint16Array(buf);
    for (var i=0, strLen=str.length; i<strLen; i++) {
         bufView[i] = str.charCodeAt(i);
    }
    return buf;
}

但是,ab2str這種寫法酸员,在實(shí)際使用中蜒车,如果buf過(guò)大讳嘱,會(huì)有Maximum call stack size exceeded堆棧溢出。

可以參考javascript - js數(shù)組轉(zhuǎn)字符串 - 在字符串和ArrayBuffers之間轉(zhuǎn)換酿愧,改為for的寫法:

var
  binaryString = '',
  bytes = new Uint8Array(arrayBuffer),
  length = bytes.length;
for (var i = 0; i < length; i++) {
  binaryString += String.fromCharCode(bytes[i]);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沥潭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嬉挡,更是在濱河造成了極大的恐慌钝鸽,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棘伴,死亡現(xiàn)場(chǎng)離奇詭異寞埠,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)焊夸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門仁连,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人阱穗,你說(shuō)我怎么就攤上這事饭冬。” “怎么了揪阶?”我有些...
    開(kāi)封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵昌抠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我鲁僚,道長(zhǎng)炊苫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任冰沙,我火速辦了婚禮侨艾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拓挥。我一直安慰自己唠梨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布侥啤。 她就那樣靜靜地躺著当叭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盖灸。 梳的紋絲不亂的頭發(fā)上蚁鳖,一...
    開(kāi)封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音赁炎,去河邊找鬼才睹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的琅攘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼松邪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坞琴!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起逗抑,我...
    開(kāi)封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤剧辐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后邮府,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體荧关,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年褂傀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忍啤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仙辟,死狀恐怖同波,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叠国,我是刑警寧澤未檩,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站粟焊,受9級(jí)特大地震影響冤狡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜项棠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一悲雳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沾乘,春花似錦怜奖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至掷匠,卻和暖如春滥崩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讹语。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工钙皮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓短条,卻偏偏與公主長(zhǎng)得像导匣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子茸时,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容