我有一个字节数组,我要将其编码为一个字符串,以便传递给浏览器中的btoa
。这些字节使用完整的0-255范围。我在btoa
看到了一开始似乎是一个错误,但是javascript的Array.prototype.join却是一个bug(或者至少是非常意外的行为)。为了说明这个问题,我将从一些base64编码的数据开始:
gACJNqQ0cg==
这可以解码为字节数组,如下所示:
atob('gACJNqQ0cg==').split('').map(c => c.charCodeAt(0))
> [128, 0, 137, 54, 164, 52, 114]
现在,您希望能够撤消操作并返回原始字符串:
btoa([128, 0, 137, 54, 164, 52, 114].map(String.fromCharCode).join(''))
但相反,你得到一个更大的字符串:
gAAAAAEAiQIANgMApAQANAUAcgYA
进一步调查时,连接使用String.fromCharCode创建的任何字符串时会出现问题:
'Hi'.split('').join('').length
> 2
'Hi'.split('').map(c => c.charCodeAt(0))
> [72, 105]
[72, 105].map(String.fromCharCode).join('').length
> 6
//what?
我在任何地方都看到了这种行为:Chrome(60),Firefox(53)和Node(6.9.4)。在浏览器中,您没有简单的替代方案,例如节点
new Buffer(array, 'binary').toString('base64')
解决此问题。如何从字节值数组中安全地创建字符串,可以将其传递给btoa
?
答案 0 :(得分:1)
如果您在map
中指定了箭头功能而不是直接将String.fromCharCode
方法传递给它,那么您的代码适合我:
console.log(btoa([128, 0, 137, 54, 164, 52, 114].map(x => String.fromCharCode(x)).join('')));
答案 1 :(得分:0)
我找到了解决这个复杂问题的简单方法:字符串连接。这是一个例子:
let str = '';
[128, 0, 137, 54, 164, 52, 114].forEach(c => {
str += String.fromCharCode(c);
});
str.length
> 7
btoa(str)
>
).join('').length
它可以工作,并且对于不是很大的字符串应该表现得足够好。但我希望看到一个更好,更清洁的解决方案,甚至只是为了更全面地了解String.fromCharCode和Array.prototype.join所发生的事情。