从 Uint8Array 到字符串的转换

rob*_*sio 10 javascript encoding character-encoding

我在从特定的 Uint8Array 转换为字符串并返回时遇到问题。我正在浏览器和 Chrome 中工作,它们本身支持 TextEncoder/TextDecoder 模块。

\n\n

如果我从一个简单的案例开始,一切似乎都很顺利:

\n\n

\nconst uintArray = new TextEncoder().encode(\'silly face demons\');\n// Uint8Array(17) [115, 105, 108, 108, 121, 32, 102, 97, 99, 101, 32, 100, 101, 109, 111, 110, 115] \nnew TextDecoder().decode(uintArray); // silly face demons\n

\n\n

但下面的案例并没有给我我期望的结果。在不涉及太多细节(与密码学相关)的情况下,让我们从以下事实开始:我提供了以下 Uint8Array:

\n\n

Uint8Array(24) [58, 226, 7, 102, 202, 238, 58, 234, 217, 17, 189, 208, 46, 34, 254, 4, 76, 249, 169, 101, 112, 102, 140, 208]

\n\n

我想做的是将其转换为字符串,然后将字符串解密回原始数组,但我得到了:

\n\n

\nconst uintArray = new Uint8Array([58, 226, 7, 102, 202, 238, 58, 234, 217, 17, 189, 208, 46, 34, 254, 4, 76, 249, 169, 101, 112, 102, 140, 208]);\nnew TextDecoder().decode(uint8Array); // :\xef\xbf\xbdf\xef\xbf\xbd\xef\xbf\xbd:\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd."\xef\xbf\xbdL\xef\xbf\xbd\xef\xbf\xbdepf\xef\xbf\xbd\xef\xbf\xbd\nnew TextEncoder().encode(\':\xef\xbf\xbdf\xef\xbf\xbd\xef\xbf\xbd:\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd."\xef\xbf\xbdL\xef\xbf\xbd\xef\xbf\xbdepf\xef\xbf\xbd\xef\xbf\xbd\');\n

\n\n

...结果是:\nUint8Array(48) [58, 239, 191, 189, 7, 102, 239, 191, 189, 239, 191, 189, 58, 239, 191, 189, 239, 191, 189, 17, 239, 191, 189, 239, 191, 189, 46, 34, 239, 191, 189, 4, 76, 239, 191, 189, 239, 191, 189, 101, 112, 102, 239, 191, 189, 239, 191, 189]

\n\n

阵列增加了一倍。编码有点超出我的掌控范围。谁能告诉我为什么数组加倍了(我假设它是原始数组的替代表示......?)。另外,更重要的是,有没有一种方法可以返回到原始数组(即,将我得到的数组解开)?

\n

Mar*_*yer 11

您尝试转换的数组中有一些utf-8没有意义或不允许的代码点。几乎所有事情都>= 128需要特殊处理。其中一些是允许的,但是多个字节序列的前导字节,而有些254是不允许的。如果您想来回转换,您需要确保您正在创建有效的utf-8. 这里的代码页布局可能有用: https: //en.wikipedia.org/wiki/UTF-8#Codepage_layout非法字节序列的描述可能有用: https: //en.wikipedia.org/wiki/UTF-8# Invalid_byte_sequences

\n\n

作为一个具体的例子,这个:

\n\n
let arr = new TextDecoder().decode(new Uint8Array([194, 169]))\nlet res = new TextEncoder().encode(arr) // => [194, 168]\n
Run Code Online (Sandbox Code Playgroud)\n\n

有效,因为[194, 169]\xc2\xa9 的 utf-8 有效,但是:

\n\n
let arr = new TextDecoder().decode(new Uint8Array([194, 27]))\nlet res = new TextEncoder().encode(arr) // => [239, 191, 189, 27]\n
Run Code Online (Sandbox Code Playgroud)\n\n

不会,因为它不是有效的序列。

\n