开发者问题收集

将较大的字节数组转换为字符串

2020-07-21
832

N 设置为 125K 时,以下操作有效

let N = 125000
let x = [...Array(N)].map(( xx,i) => i)
let y = String.fromCodePoint(...x)
console.log(y.length)

当 N 设置为 128K 时,相同的代码会中断:

Uncaught RangeError: Maximum call stack size exceeded

这是一个常见操作:实现转换的最佳方法是什么?

请注意,我确实查看了相关的问答。 https://stackoverflow.com/a/3195961/1056563 我们不应该依赖 node.js ,而且使用 fromCharCode.apply 的方法也失败了。最后,这个答案已经有近十年了。

那么,处理这种转换的最新、最有效的方法是什么呢?

3个回答

问题是由于 实现 接受的参数数量 限制 。当通过扩展运算符向 String.fromCodePoint 函数提供过多参数(在本例中超过 ~128k)时,会导致引发异常。

虽然代码量略多,但 相对高效 解决此问题的一种方法是跨多个调用批量执行操作。这是我提议的实现,它修复了我认为与扩展性能 代理对 的处理有关的问题(这是不正确的: fromCodePoint 不关心代理,因此在这种情况下它比 fromCharCode 更可取)。

957188​​596

另外,我想要一个奖杯。上面的代码应该在 O(n) 时间内运行,并尽量减少分配的对象数量。不能保证这是“最佳”方法。批处理方法的一个好处,以及为什么 apply (或扩展调用)的成本被纳入,是 String.fromCodePoint 和中间字符串的调用次数显着减少。 YMMV - 尤其是在不同环境中。

这是一个 在线基准 。所有测试都可以访问并使用相同的生成的 500k 个元素的“A”数组。

在此处输入图片说明

user2864740
2020-07-21

给出的答案性能不佳:我测量了其中一个答案的 19 秒,其他答案也差不多 (*)。必须 预分配 输出数组。接下来是 20 到 40 毫秒 秒。快了三个数量级。

function wordArrayToByteArray(hash) {
    var result = [...Array(hash.sigBytes)].map(x => -1)
    let words = hash.words
        //map each word to an array of bytes
        .map(function (v) {
            // create an array of 4 bytes (less if sigBytes says we have run out)
            var bytes = [0, 0, 0, 0].slice(0, Math.min(4, hash.sigBytes))
                // grab that section of the 4 byte word
                .map(function (d, i) {
                    return (v >>> (8 * i)) % 256;
                })
                // flip that
                .reverse()
            ;
            // remove the bytes we've processed
            // from the bytes we need to process
            hash.sigBytes -= bytes.length;
            return bytes;
        })
    words.forEach((w,i) => {
        result.splice(i * 4, 4, ...w)
    })
    result = result.map(function (d) {
        return String.fromCharCode(d);
    }).join('')
    return result
}

(*) 除了 @User2864740 可能例外 - 我们正在等待他的数字。但他的解决方案也在循环内使用了 apply() ,这导致相信它也会很慢。

WestCoastProjects
2020-07-21

“老式” JavaScript:

var N=125000;
var y="";
for(var i=0; i<N; i++)
  y+=String.fromCharCode(i);
console.log(y.length);

使用 N=1000000

iAmOren
2020-07-21