【问题标题】:Array.join inserts extra characters when joining strings created with String.fromCharCodeArray.join 在连接使用 String.fromCharCode 创建的字符串时插入额外的字符
【发布时间】:2017-07-15 03:52:08
【问题描述】:

我有一个字节数组,我想将其编码为字符串以传递给浏览器中的btoa。这些字节使用完整的 0-255 范围。起初我遇到了btoa 的错误,但事实证明这是javascript 的 Array.prototype.join 的错误(或至少是相当意外的行为)。为了说明问题,我将从一些 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)。在浏览器中,您没有简单的替代方案,例如 node 的 new Buffer(array, 'binary').toString('base64') 来解决这个问题。如何安全地从字节值数组创建字符串,并将其传递给btoa

【问题讨论】:

  • String.fromCharCode 被多个参数调用(因为map 以这种方式工作),这就是你得到不同结果的原因。

标签: javascript character-encoding fromcharcode


【解决方案1】:

如果您在 map 中指定箭头函数而不是直接将 String.fromCharCode 方法传递给它,那么您的代码对我有用:

console.log(btoa([128, 0, 137, 54, 164, 52, 114].map(x => String.fromCharCode(x)).join('')));

【讨论】:

  • 使用 ES6,你可以使用扩展语法:String.fromCharCode(...theArray)
  • 哦,当然! String.fromCharCode 有多个参数,可以返回多个字符的字符串,所以传入的是索引。我现在感觉很笨。不删除这个问题需要一些克制。
【解决方案2】:

我找到了一个解决这个复杂问题的简单方法:字符串连接。这是一个例子:

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 的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-23
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 2017-04-21
    • 2023-03-12
    相关资源
    最近更新 更多