我的应用会生成包含十六进制字符串的链接:37c1fbcabbc31f2f8d2ad31ceb91cd8d0d189ca5963dc6d353188d3d5e75b8b3e401d4e74e9b3e02efbff0792cda5c4620cb3b1f84aeb47b8d2225cd40e761a5
。我真的想让它们更短,就像Compressing a hex string in Ruby/Rails中提到的Ruby解决方案一样。
有没有办法在JavaScript / NodeJS中执行此操作?
答案 0 :(得分:4)
您可以使用toString和parseInt方法,这基本上与您在链接中提到的方法做同样的事情:
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支持最多36,所以你需要手动实现personal notation(I相信已经有一些实施了。)
答案 1 :(得分:2)
最简单快速的事情是定义一组64个安全字符,用于URL,例如A-Z,a-z,0-9,_和$。然后将每三个十六进制数字(每个4位)编码为两个安全字符(每个6位)。这不需要乘法和除法,它可以用在任意长的字符串上。
您需要在字符串末尾选择要使用的第65个字符,以指示是否使用了最后的四位字符。否则,对于具有偶数个字符的字符串,您将具有歧义。我们称之为 2n 。然后有 3n-1 或 3n 十六进制数字编码,但没有办法告诉哪个。您可以使用特殊字符跟踪序列以指示其中一个案例。例如。一个 '。' (周期)。
注意:此处为集合选择的最后几个字符与Base64编码不同,因为URL有自己的安全标点符号定义。请参阅RFC 1738。
答案 2 :(得分:2)
节点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'