Javascript 大数数组压缩

Javascript 大数数组压缩,javascript,compression,Javascript,Compression,我有一个javascript应用程序,它可以发送大量的数字数据。然后,这些数据存储在数据库中。我有大小问题(带宽太大,数据库太大)。我现在准备牺牲一些性能来压缩 我在考虑实现一个base 62 number.toString(62)和parseInt(compressed,62)。这当然会减少数据的大小,但在我继续做这件事之前,我想我会把它告诉这里的人们,因为我知道一定有一些我没有考虑过的开箱即用的解决方案 基本规格为: -将大量数组压缩成字符串以进行JSONP传输(因此我认为UTF已过时) -

我有一个javascript应用程序,它可以发送大量的数字数据。然后,这些数据存储在数据库中。我有大小问题(带宽太大,数据库太大)。我现在准备牺牲一些性能来压缩

我在考虑实现一个base 62 number.toString(62)和parseInt(compressed,62)。这当然会减少数据的大小,但在我继续做这件事之前,我想我会把它告诉这里的人们,因为我知道一定有一些我没有考虑过的开箱即用的解决方案

基本规格为: -将大量数组压缩成字符串以进行JSONP传输(因此我认为UTF已过时) -要相对快一些,看,我不期望像现在这样的性能,但我也不希望gzip压缩

任何想法都将不胜感激

谢谢

Guido Tapia

选项

  • 使用js库(参见Josh的答案),但要注意脚本超时
  • 使用某种activex或silverlight上传程序,也可以进行压缩
  • 使用java插件
  • 使用基于flash的压缩上传程序

另一种方法可能是编码为二进制类型,如有符号/无符号整数,并手动解码,这将需要服务器端代码来创建二进制数据

然后,您可以使用哈夫曼压缩或类似于RLE的方法(请参阅实现,尽管IE中可能存在一些问题,但不需要修改),进一步压缩数据

编辑: 或者,您可以将数字本身转换为未编码URI字符范围(请参阅)中的基(基数),如果其中许多数字大于2位,则该转换应能正常工作。我将python中的代码转换为

它目前不处理浮动,但可以相当容易地完成:

function get_map(s) {
    d = {}
    for (var i=0; i<s.length; i++) {
        d[s.charAt(i)] = i}
    d.length = s.length
    d._s = s
    return d}

var separate_with = '~';
var encodable = get_map('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.'); // - is reserved for negatives obviously :-P
var base10 = get_map('0123456789')

// UNCOMMENT ME for length/speed testing in a wider base!
// You may wish to experiment with the ranges for a happy medium between bandwidth and DB space :-P
/*var encodable = ''
for (var i=1; i<128; i++) {
    encodable += String.fromCharCode(i)
}
encodable = get_map(encodable)*/

function baseconvert(number, fromdigits, todigits) {
    var number = String(number)

    if (number.charAt(0) == '-') {
        number = number.slice(1, number.length)
        neg=1}
    else {
        neg=0}

    // make an integer out of the number
    var x = 0
    for (var i=0; i<number.length; i++) {
        var digit = number.charAt(i)
        x = x*fromdigits.length + fromdigits[digit]
    }

    // create the result in base 'todigits.length'
    res = ""
    while (x>0) {
        remainder = x % todigits.length
        res = todigits._s.charAt(remainder) + res
        x = parseInt(x/todigits.length)
    }

    if (neg) res = "-"+res
    return res
}

function encodeNums(L) {
    var r = []
    for (var i=0; i<L.length; i++) {
         r.push(baseconvert(L[i], base10, encodable))
    }
    return r.join(separate_with)
}

function decodeNums(s) {
    var r = []
    var s = s.split(separate_with)
    for (var i=0; i<s.length; i++) {
         r.push(parseInt(baseconvert(s[i], encodable, base10)))
    }
    return r
}

var test = [5, 654645, 24324, 652124, 65, 65289543, 65278432, 643175874158, 652754327543]
alert(encodeNums(test))
alert(decodeNums(encodeNums(test)))
函数获取地图{
d={}

对于(var i=0;i我现在正在考虑将数字的长度编码到数字本身中。我仍然没有完善这个算法,但一旦完成就会发布。但大致上这就是我目前试图实现的目标:

边界:

  • 允许精度损失(+-3)
  • 最大数量为3200
  • 最小值为0(因此没有负片)
  • 没有十进制浮点数
现在给我的最大允许数,我知道基62中编码数字的最大长度为2。所以任何编码数字的长度都是1或2个字符。太棒了。所以现在我要根据数字的1或2个字符将其设为奇数或偶数(记住我可以处理精度损失)。这样就不需要使用分离器


现在我看到这种方法有70%-80%的压缩率,目前它有很多问题,但我对此感到很兴奋,所以这篇文章鼓励大家围绕这种方法进行讨论。

为什么不使用gzip?这有什么问题?(或者更可能的是,缩小)如果你想让它更简单的话,你也可以做一些类似于Huffman或LZW的事情。Huffman用Javascript编码:为了清楚起见-我们是通过Javascript和ajax/jsonp将数据从客户端发送到服务器的?@James:对,我们将一个非常大的数组作为字符串发送到服务器。数组不是JSON格式的(所以没有愚蠢的xml标记-哎呀,我是指大括号)只有一个字符串。在int之间连接('.')。这个字符串还存储在数据库中(这是真正的大小问题)。@Cheeso:我不想在服务器上加载压缩/解压缩。我想要客户端(浏览器)除非你能想出一种在JS中使用复杂压缩算法的方法,否则gzip就不存在了。@nick:我们说的是每个约200k的请求。我们说的是每天约100000个请求,我们保留2周的数据,但是每天100000个请求在增加:)如果我能将这些请求设置为100k,那么我将可以在当前硬件设置的情况下再使用至少6个月。这是我在初始问题(base 62编码)中提出的建议。不过,您的示例确实增加了使用更大基数(128)的可能性然而,我怀疑JSONP传输是否正确,我认为62与它将得到的一样好。感谢代码tho,我将与我的代码进行性能比较。仅供参考,此代码将创建一组全局变量。您可能需要更新它。在get_map:d中将是一个全局变量,在baseconvert中:res、neg和余数都将创建global变量。在那之后我停止了阅读,但这个想法似乎很有趣……如果允许使用二进制,我会使用每个字符中8位中的第一位来询问数字是否继续,但保留31个字符用于“继续”,保留31个字符用于“停止”可能也会起作用。再说一次,你可能已经通过它的声音想到了:-)