【问题标题】:Issues with compression in javascriptjavascript中的压缩问题
【发布时间】:2015-07-03 17:02:35
【问题描述】:

我有一个要压缩的对象。它的形式是

[
  {
    array
    string
  },
  {
    array
    string
  },
  ...
]

数组的长度不超过 10-15,与字符串相比非常小(它们是 html,长度大约为 170k)。但是这些字符串通常是重复的,或者有大量的重叠。所以我的直觉告诉我压缩的值应该是1个字符串的压缩值,再加一点。

我 JSON.stringify 这个对象并尝试压缩。

大多数压缩库在压缩字符串方面做得不好,因为服务器向我发送了一个 77kb 的 gzip 压缩版本,我知道它至少可以这么小。

gzip-js

lzma-js

在我尝试的 15 个库中做得很好。

问题是 gzip-js 在字符串数量上是线性的。但是 lzma 正确地做到了这一点,它只是稍微增加了大小。

不幸的是,Lzma-js(2 级)在压缩 7mbs(大约 30~ 个字符串)时非常慢(20s vs 1s gzip)。

是否有一个 compressopn 库,它与 gzip 大致一样快,但不能在重复字符串上线性缩放?

【问题讨论】:

标签: javascript compression gzip lzma


【解决方案1】:

Pako对我有用,试试看:

不要使用字符串 id,而是使用 byteArrays,就像 here 所做的那样。

获取pako.js,就可以像这样解压byteArray:

<html>
<head>
<title>Gunzipping binary gzipped string</title>
<script type="text/javascript" src="pako.js"></script>
<script type="text/javascript">

// Get datastream as Array, for example:
var charData    = [31,139,8,0,0,0,0,0,0,3,5,193,219,13,0,16,16,4,192,86,214,151,102,52,33,110,35,66,108,226,60,218,55,147,164,238,24,173,19,143,241,18,85,27,58,203,57,46,29,25,198,34,163,193,247,106,179,134,15,50,167,173,148,48,0,0,0];

// Turn number array into byte-array
var binData     = new Uint8Array(charData);

// Pako magic
var data        = pako.inflate(binData);

// Convert gunzipped byteArray back to ascii string:
var strData     = String.fromCharCode.apply(null, new Uint16Array(data));

// Output to console
console.log(strData);

</script>
</head>
<body>
Open up the developer console.
</body>
</html>

运行示例:http://jsfiddle.net/9yH7M/

或者,您可以在发送数组之前对数组进行 base64 编码,因为当以 JSON 或 XML 发送时,数组会占用大量开销。同样解码:

// Get some base64 encoded binary data from the server. Imagine we got this:
var b64Data     = 'H4sIAAAAAAAAAwXB2w0AEBAEwFbWl2Y0IW4jQmziPNo3k6TuGK0Tj/ESVRs6yzkuHRnGIqPB92qzhg8yp62UMAAAAA==';

// Decode base64 (convert ascii to binary)
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);

// Pako magic
var data        = pako.inflate(binData);

// Convert gunzipped byteArray back to ascii string:
var strData     = String.fromCharCode.apply(null, new Uint16Array(data));

// Output to console
console.log(strData);

运行示例:http://jsfiddle.net/9yH7M/1/

如需更多高级功能,请阅读pako API documentation

【讨论】:

    【解决方案2】:

    使用高压缩级别的 gzip-js 库
    https://github.com/beatgammit/gzip-js

    var gzip = require('gzip-js'),
        options = {
            level: 9,
            name: 'hello-world.txt',
            timestamp: parseInt(Date.now() / 1000, 10)
        };
    
    // out will be a JavaScript Array of bytes
    var out = gzip.zip('Hello world', options);
    

    我发现这种方式在正常持续时间的情况下尽可能小

    对于基于 LZ 的压缩算法,我认为 lz-string 更快
    检查您的数据样本
    https://github.com/pieroxy/lz-string

    【讨论】:

      猜你喜欢
      • 2017-01-02
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 2012-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多