【问题标题】:Converting from a Uint8Array to a string and back从 Uint8Array 转换为字符串并返回
【发布时间】:2018-12-24 13:56:53
【问题描述】:

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

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

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

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

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]

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

const 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]); new TextDecoder().decode(uint8Array); // :�f��:����."�L��epf�� new TextEncoder().encode(':�f��:����."�L��epf��');

...导致: Uint8Array(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]

数组增加了一倍。编码有点超出我的驾驶室。谁能告诉我为什么数组翻了一番(我假设它是原始数组的替代表示......?)。另外,更重要的是,有没有一种方法可以让我恢复到原始数组(即,将我得到的数组取消两倍)?

【问题讨论】:

  • 很简单:不是所有的字节值都对应字符串字符。不是 ASCII 或 unicode。还有误用加密/解密编码/解码,它们不是一回事。
  • 如果您只想将其转换为字符串并返回并获取对应的值,您可以这样做:var str = String.fromCharCode(...uintArray) 然后Uint8Array.from([...str].map(ch => ch.charCodeAt()))

标签: javascript encoding character-encoding


【解决方案1】:

您尝试将数组中的代码点转换为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

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

let arr = new TextDecoder().decode(new Uint8Array([194, 169]))
let res = new TextEncoder().encode(arr) // => [194, 168]

之所以有效,是因为[194, 169] 对于 © 是有效的 utf-8,但是:

let arr = new TextDecoder().decode(new Uint8Array([194, 27]))
let res = new TextEncoder().encode(arr) // => [239, 191, 189, 27]

不是因为它不是一个有效的序列。

【讨论】:

  • 谢谢。这就说得通了。我想我可能只是在这里使用了错误的编码。也许 base64 会帮助我?
  • 只是为了记录.. base64 对我有用。我想我只是在我的 Uint8Array 中有无法用 utf8 表示的代码点。
  • 可能永远不应该将 UTF-8 用于此类工作。由于来自“individual”字节的字符串应该是单字节字符集,其中不存在无效字符之类的东西,尤其是位映射时。
猜你喜欢
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2019-12-17
  • 2016-02-05
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多