5

我的应用程序生成链接,其中包含十六进制字符串,如:37c1fbcabbc31f2f8d2ad31ceb91cd8d0d189ca5963dc6d353188d3d5e75b8b3e401d4e74e9b3e02efbff0792cda5c4620cb3b1f84aeb47b8d2225cd40e761a5。我真的想让它们更短,就像 Ruby 在Compressing a hex string in Ruby/Rails中提到的解决方案一样。

有没有办法在 JavaScript/NodeJS 中做到这一点?

4

3 回答 3

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);

更新:您也可以使用 base 62 而不是 36 来压缩更多,但请注意 JS 最多支持 base 36,因此您需要手动实现该个人符号(我相信已经有一些实现)。

于 2012-08-02T10:15:55.623 回答
3

node 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'
于 2012-11-09T01:32:03.263 回答
2

最简单、最快的做法是定义一组 64 个安全字符以供在 URL 中使用,例如 AZ、az、0-9、_ 和 $。然后将每三个十六进制数字(每个 4 位)编码为两个安全字符(每个 6 位)。这不需要乘法和除法,它可以用于任意长的字符串。

您需要在字符串末尾选择第 65 个字符以指示是否使用了最后一个四位片段。否则,对于偶数个字符的字符串,您将产生歧义。我们称之为2n。然后有3n-13n 个十六进制数字在其中编码,但无法分辨是哪个。您可以按照顺序使用特殊字符来指示其中一种情况。例如“。” (时期)。

注意:此处为集合选择的最后几个字符与 Base64 编码不同,因为 URL 有自己的安全标点字符定义。请参阅RFC 1738

于 2012-08-02T23:25:59.703 回答