将大数组整数转换为unicodestring,然后返回到node.js中的整数数组

我有一些数据表示为一个整数数组,可以达到20万个元素。 整数值可以从0到200 000变化。

要模拟这些数据(用于debugging目的),我可以执行以下操作:

let data = []; let len = 200000 for (let i = 0; i < len; i++) { data[i] = i; } 

要将这个整数数组作为一个Unicodestring我执行此操作:

 let dataAsText = data.map((e) => { return String.fromCodePoint(e); }).join(''); 

当我想要转换回整数数组看起来更长:

 let dataBack = dataAsText.split('').map((e) => { return e.codePointAt(e); }); console.log(dataBack.length); 

它是怎么来的? 哪里不对 ?

额外的信息:

  • 我使用codePointAt / fromCodePoint,因为它可以处理所有的Unicode值(高达21位),而charCodeAt / fromCharCode失败。

  • 例如,使用.join('123')和.split('123')将使variablesdataBack与数据的长度相同。 但是这不是一个很好的解决scheme,因为stringdataAsText的大小将不必要地非常大。

  • 如果让len等于或小于65536(即2 ^ 16或16位最大值),那么一切正常。 这很奇怪?

编辑:

我使用codePoint,因为我需要将数据转换为unicode文本,以便数据很短。

更多关于codePoint vs charCode的例子:如果我们将150000转换为一个字符,然后返回一个带有codePoint的整数:

 console.log(String.fromCodePoint("150000").codePointAt(0)); 

这给了我们150000这是正确的。 用charCode做同样的失败并打印18928(而不是150000):

 console.log(String.fromCharCode("150000").charCodeAt(0)); 

       

网上收集的解决方案 "将大数组整数转换为unicodestring,然后返回到node.js中的整数数组"

这是因为更高的代码点值将产生2个单词,正如可以在这个片段中看到的那样:

 var s = String.fromCodePoint(0x2F804) console.log(s); // Shows one character console.log('length = ', s.length); // 2, because encoding is \uD87E\uDC04 var i = s.codePointAt(0); console.log('CodePoint value at 0: ', i); // correct var i = s.codePointAt(1); // Should not do this, it starts in the middle of a sequence! console.log('CodePoint value at 1: ', i); // misleading 

我有一种感觉拆分不符合unicode值,65536以上的快速testing表明,他们成为分裂后长度的两倍

也许看看这个post和答案 ,因为他们提出类似的问题

我不认为你想要charPointAt (或charCodeAt )。 要将数字转换为string,只需使用String ; 有一个带有所有值的单个分隔string,使用分隔符(如, ); 将其转换回数字,使用Number ,一元+parseIntparseFloat (在你的情况下, Number+可能)适当的一个:

 // Only 20 instead of 200000 let data = []; for (let i = 199980; i < 200000; i++) { data.push(i); } let dataAsText = data.join(","); console.log(dataAsText); let dataBack = dataAsText.split(",").map(Number); console.log(dataBack); 

如果您正在寻找对整数列表进行编码的方法,以便您可以通过networking安全地传输它,则使用base64编码的节点缓冲区可能是更好的select:

 let data = []; for (let i = 0; i < 200000; i++) { data.push(i); } // encoding var ta = new Int32Array(data); var buf = Buffer.from(ta.buffer); var encoded = buf.toString('base64'); // decoding var buf = Buffer.from(encoded, 'base64'); var ta = new Uint32Array(buf.buffer, buf.byteOffset, buf.byteLength >> 2); var decoded = Array.from(ta); // same? console.log(decoded.join() == data.join()) 

您的原始方法将无法正常工作,因为不是每个整数在Unicode中都有相应的代码点。

UPD:如果你不需要数据是二进制安全的,不需要base64,只需要存储缓冲区:

 // saving var ta = new Int32Array(data); fs.writeFileSync('whatever', Buffer.from(ta.buffer)); // loading var buf = fs.readFileSync('whatever'); var loadedData = Array.from(new Uint32Array(buf.buffer, buf.byteOffset, buf.byteLength >> 2)); // same? console.log(loadedData.join() == data.join())