将大数组整数转换为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));
这是因为更高的代码点值将产生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
,一元+
, parseInt
或parseFloat
(在你的情况下, 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())