在JavaScript/NodeJS中压缩一个十六进制字符串

5
我的应用程序生成包含十六进制字符串的链接,例如:37c1fbcabbc31f2f8d2ad31ceb91cd8d0d189ca5963dc6d353188d3d5e75b8b3e401d4e74e9b3e02efbff0792cda5c4620cb3b1f84aeb47b8d2225cd40e761a5。我希望将它们缩短,就像在Ruby / Rails中提到的解决方案一样。请问在JavaScript / NodeJS中有办法吗?
3个回答

4

使用已经提到的策略,int-encoder 可以实现此功能。

它还支持大数值。

npm install int-encoder

var en = require('int-encoder');

//simple integer conversion
en.encode(12345678); // "ZXP0"
en.decode('ZXP0'); // 12345678

//convert big hex number using optional base argument
en.encode('e6c6b53d3c8160b22dad35a0f705ec09', 16); // 'hbDcW9aE89tzLYjDgyzajJ'
en.decode('hbDcW9aE89tzLYjDgyzajJ', 16); // 'e6c6b53d3c8160b22dad35a0f705ec09'

4
你可以使用toStringparseInt方法,这两个方法基本上与你在链接中提到的方法是相同的。
var hexString = "4b3fc1400";
var b36 = parseInt(hexString, 16).toString(36); // "9a29mgw"

要将其转换回来,您只需要做相反的操作:

hexString = parseInt(b36, 36).toString(16); // "4b3fc1400"

你的字符串唯一的问题在于它太大了,在JavaScript中无法当作数字处理。你应该将它们分成块。JavaScript的数字精确度最高可达2^53(加号),所以你可以处理的最大正数是0x20000000000000(十六进制表示,即9007199254740992的十进制表示);你可以利用这种精度来处理块:
var hexString = "37c1fbcabbc31f2f8d2ad31ceb91cd8d0d189ca5963dc6d353188d3d5e75b8b3e401d4e74e9b3e02efbff0792cda5c4620cb3b1f84aeb47b8d2225cd40e761a5"

var b36 = "", b16 = "";

var chunk, intChunk;

// 14 is the length of 0x20000000000000 (2^53 in base 16)

for (var i = 0, max = 14; i < hexString.length; i += max) {
    chunk = hexString.substr(i, max);
    intChunk = parseInt(chunk, 16);

    if (intChunk.toString(16) !== chunk) {
        intChunk = parseInt(hexString.substr(i, max - 1), 16);
        i -= 1;
    }

    b36 += intChunk.toString(36)
}

// 11 is the length of 2gosa7pa2gv (2^53 in base 36)

for (var i = 0, max = 11; i < b36.length; i += max ) {
    chunk = b36.substr(i, max);
    intChunk = parseInt(chunk, 36);

    if (intChunk.toString(36) !== chunk) {
        intChunk = parseInt(b36.substr(i, max - 1), 36);
        i -= 1;
    }

    b16 += intChunk.toString(16)
}

console.log(hexString);
console.log(b36);
console.log(b16);
更新: 你也可以使用基于62进制而不是36进制来进行更多的压缩,但请注意JS仅支持最高36进制,因此你需要手动实现个人注释(我相信已经有一些实现了)。

我该如何将字符串转换为Base36,我需要尝试学习Reddit的API,其中完整名称是t2_36basesencodedHere。请参考http://www.reddit.com/dev/api#fullnames。 - Muhammad Umer

2
最简单和最快的方法是定义一组64个安全字符用于URL,例如A-Z,a-z,0-9,_和$。然后将每三个十六进制数字(每个4位)编码为两个安全字符(每个6位)。这不需要乘法和除法,并且可以用于任意长度的字符串。
你需要选择一个65个字符来在字符串结尾使用,以指示是否使用了最后四位二进制数。否则,对于具有偶数个字符的字符串,会出现歧义。我们将其称为2n。然后,在其中编码了三个或三个以上的十六进制数,但是没有办法确定哪个是哪个。您可以跟随一个特殊字符以指示其中一个情况。例如一个.(点)。
注意:此处为集合选择的最后几个字符与Base64编码不同,因为URL具有自己的安全标点字符定义。请参见RFC 1738

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接