我有一些UTF-8编码数据存在于Javascript中的一系列Uint8Array元素中.有没有一种有效的方法将这些解码为常规的javascript字符串(我相信Javascript使用16位Unicode)?我不希望当时添加一个字符,因为字符串concaternation将变为CPU密集型.
Vin*_*eib 136
TextEncoder
和TextDecoder
从所述编码标准,这是由polyfilled stringencoding库,将字符串转换和ArrayBuffers之间:
var uint8array = new TextEncoder("utf-8").encode("¢");
var string = new TextDecoder("utf-8").decode(uint8array);
Run Code Online (Sandbox Code Playgroud)
Alb*_*ert 38
这应该工作:
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
/* utf.js - UTF-8 <=> UTF-16 convertion
*
* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
* Version: 1.0
* LastModified: Dec 25 1999
* This library is free. You can redistribute it and/or modify it.
*/
function Utf8ArrayToStr(array) {
var out, i, len, c;
var char2, char3;
out = "";
len = array.length;
i = 0;
while(i < len) {
c = array[i++];
switch(c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
}
Run Code Online (Sandbox Code Playgroud)
它与其他解决方案相比更加清晰,因为它不使用任何hacks,也不依赖于Browser JS功能,例如也适用于其他JS环境.
查看JSFiddle演示.
arc*_*en7 35
在 NodeJS 中,我们有可用的缓冲区,并且使用它们进行字符串转换非常容易。更好的是,将 Uint8Array 转换为 Buffer 很容易。试试这个代码,它在 Node 中对我来说适用于基本上任何涉及 Uint8Arrays 的转换:
let str = Buffer.from(uint8arr.buffer).toString();
Run Code Online (Sandbox Code Playgroud)
我们只是从 Uint8Array 中提取 ArrayBuffer,然后将其转换为正确的 NodeJS 缓冲区。然后我们将 Buffer 转换为字符串(如果需要,您可以输入十六进制或 base64 编码)。
如果我们想从字符串转换回 Uint8Array,那么我们可以这样做:
let uint8arr = new Uint8Array(Buffer.from(str));
Run Code Online (Sandbox Code Playgroud)
请注意,如果您在转换为字符串时声明了类似 Base64 的编码,那么您必须使用Buffer.from(str, "base64")
Base64 或您使用的任何其他编码。
如果没有模块,这将无法在浏览器中运行!NodeJS Buffers 在浏览器中不存在,因此除非您向浏览器添加 Buffer 功能,否则此方法将不起作用。这实际上很容易做到,只需使用这样的模块即可,它既小又快!
dlc*_*ers 24
这是我使用的:
var str = String.fromCharCode.apply(null, uint8Arr);
Run Code Online (Sandbox Code Playgroud)
Wil*_*ott 16
在其中一个Chrome示例应用程序中找到,虽然这适用于较大的数据块,您可以使用异步转换.
/**
* Converts an array buffer to a string
*
* @private
* @param {ArrayBuffer} buf The buffer to convert
* @param {Function} callback The function to call when conversion is complete
*/
function _arrayBufferToString(buf, callback) {
var bb = new Blob([new Uint8Array(buf)]);
var f = new FileReader();
f.onload = function(e) {
callback(e.target.result);
};
f.readAsText(bb);
}
Run Code Online (Sandbox Code Playgroud)
kpo*_*owz 10
在节点" Buffer
实例也是Uint8Array
实例 "中,因此buf.toString()
在这种情况下工作.
只要很少调用所提供的函数,并且仅用于中等大小的数组,Albert给出的解决方案就可以很好地工作,否则效率极低。这是一个增强的Vanilla JavaScript解决方案,可同时用于Node和浏览器,并具有以下优点:
•有效地适用于所有八位字节数组大小
•不产生中间的一次性字符串
•在现代JS引擎上支持4字节字符(否则用“?”代替)
var utf8ArrayToStr = (function () {
var charCache = new Array(128); // Preallocate the cache for the common single byte chars
var charFromCodePt = String.fromCodePoint || String.fromCharCode;
var result = [];
return function (array) {
var codePt, byte1;
var buffLen = array.length;
result.length = 0;
for (var i = 0; i < buffLen;) {
byte1 = array[i++];
if (byte1 <= 0x7F) {
codePt = byte1;
} else if (byte1 <= 0xDF) {
codePt = ((byte1 & 0x1F) << 6) | (array[i++] & 0x3F);
} else if (byte1 <= 0xEF) {
codePt = ((byte1 & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
} else if (String.fromCodePoint) {
codePt = ((byte1 & 0x07) << 18) | ((array[i++] & 0x3F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
} else {
codePt = 63; // Cannot convert four byte code points, so use "?" instead
i += 3;
}
result.push(charCache[codePt] || (charCache[codePt] = charFromCodePt(codePt)));
}
return result.join('');
};
})();
Run Code Online (Sandbox Code Playgroud)
Uint8Array 到 String
let str = Buffer.from(key.secretKey).toString('base64');
Run Code Online (Sandbox Code Playgroud)
字符串到 Uint8Array
let uint8arr = new Uint8Array(Buffer.from(data,'base64'));
Run Code Online (Sandbox Code Playgroud)
我很沮丧地看到人们没有展示如何进行双向操作,也没有展示如何在不简单的 UTF8 字符串上工作。我在 codereview.stackexchange.com 上找到了一篇文章,其中有一些运行良好的代码。我用它把古代符文转换成字节,测试字节上的一些密码,然后将东西转换回字符串。工作代码位于 github上。为了清楚起见,我重命名了这些方法:
\n\n// https://codereview.stackexchange.com/a/3589/75693\nfunction bytesToSring(bytes) {\n var chars = [];\n for(var i = 0, n = bytes.length; i < n;) {\n chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));\n }\n return String.fromCharCode.apply(null, chars);\n}\n\n// https://codereview.stackexchange.com/a/3589/75693\nfunction stringToBytes(str) {\n var bytes = [];\n for(var i = 0, n = str.length; i < n; i++) {\n var char = str.charCodeAt(i);\n bytes.push(char >>> 8, char & 0xFF);\n }\n return bytes;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n单元测试使用以下 UTF-8 字符串:
\n\n // http://kermitproject.org/utf8.html\n // From the Anglo-Saxon Rune Poem (Rune version) \n const secretUtf8 = `\xe1\x9a\xa0\xe1\x9b\x87\xe1\x9a\xbb\xe1\x9b\xab\xe1\x9b\x92\xe1\x9b\xa6\xe1\x9a\xa6\xe1\x9b\xab\xe1\x9a\xa0\xe1\x9a\xb1\xe1\x9a\xa9\xe1\x9a\xa0\xe1\x9a\xa2\xe1\x9a\xb1\xe1\x9b\xab\xe1\x9a\xa0\xe1\x9b\x81\xe1\x9a\xb1\xe1\x9a\xaa\xe1\x9b\xab\xe1\x9a\xb7\xe1\x9b\x96\xe1\x9a\xbb\xe1\x9a\xb9\xe1\x9b\xa6\xe1\x9b\x9a\xe1\x9a\xb3\xe1\x9a\xa2\xe1\x9b\x97\n\xe1\x9b\x8b\xe1\x9a\xb3\xe1\x9b\x96\xe1\x9a\xaa\xe1\x9b\x9a\xe1\x9b\xab\xe1\x9a\xa6\xe1\x9b\x96\xe1\x9a\xaa\xe1\x9a\xbb\xe1\x9b\xab\xe1\x9b\x97\xe1\x9a\xaa\xe1\x9a\xbe\xe1\x9a\xbe\xe1\x9a\xaa\xe1\x9b\xab\xe1\x9a\xb7\xe1\x9b\x96\xe1\x9a\xbb\xe1\x9a\xb9\xe1\x9b\xa6\xe1\x9b\x9a\xe1\x9a\xb3\xe1\x9b\xab\xe1\x9b\x97\xe1\x9b\x81\xe1\x9a\xb3\xe1\x9b\x9a\xe1\x9a\xa2\xe1\x9a\xbe\xe1\x9b\xab\xe1\x9a\xbb\xe1\x9b\xa6\xe1\x9b\x8f\xe1\x9b\xab\xe1\x9b\x9e\xe1\x9a\xab\xe1\x9b\x9a\xe1\x9a\xaa\xe1\x9a\xbe\n\xe1\x9a\xb7\xe1\x9b\x81\xe1\x9a\xa0\xe1\x9b\xab\xe1\x9a\xbb\xe1\x9b\x96\xe1\x9b\xab\xe1\x9a\xb9\xe1\x9b\x81\xe1\x9b\x9a\xe1\x9b\x96\xe1\x9b\xab\xe1\x9a\xa0\xe1\x9a\xa9\xe1\x9a\xb1\xe1\x9b\xab\xe1\x9b\x9e\xe1\x9a\xb1\xe1\x9b\x81\xe1\x9a\xbb\xe1\x9b\x8f\xe1\x9a\xbe\xe1\x9b\x96\xe1\x9b\xab\xe1\x9b\x9e\xe1\x9a\xa9\xe1\x9b\x97\xe1\x9b\x96\xe1\x9b\x8b\xe1\x9b\xab\xe1\x9a\xbb\xe1\x9b\x9a\xe1\x9b\x87\xe1\x9b\x8f\xe1\x9a\xaa\xe1\x9a\xbe\xe1\x9b\xac`;\n
Run Code Online (Sandbox Code Playgroud)\n\n请注意,字符串长度仅为 117 个字符,但编码后的字节长度为 234。
\n\n如果我取消注释 console.log 行,我可以看到解码的字符串与编码的字符串相同(字节通过 Shamir 的秘密共享算法传递!):
\n\n\n小智 5
执行@Sudhir所说的,然后从逗号分隔的数字列表中获取字符串,请使用:
for (var i=0; i<unitArr.byteLength; i++) {
myString += String.fromCharCode(unitArr[i])
}
Run Code Online (Sandbox Code Playgroud)
如果仍然有用,它将为您提供所需的字符串