TextEncoder提供额外的字节,TextDecoder为具有负值的数组字节提供错误的字符串

时间:2016-11-23 12:18:24

标签: javascript

  arr = new Int8Array([-1,-1],0); // gives [-1,-1]

  str = new TextDecoder('utf-8').decode(arr); // gives "��"

  res = new TextEncoder('utf-8').encode(str); // gives [239, 191, 189, 239, 191, 189] instead of [-1,-1]

它不适用于负值。完美地为正面工作。还有其他选择吗?

1 个答案:

答案 0 :(得分:2)

第1部分:字节不是

TextDecoder接口对Int8Array视图包装的底层ArrayBuffer(字节序列)进行操作。

此:

new TextDecoder('utf-8').decode(new Int8Array([-1, -1]))

与:

相同
new TextDecoder('utf-8').decode(new Int8Array([-1, -1]).buffer)

哪个是包含字节0xFF,0xFF的ArrayBuffer。所以它与:

相同
new TextDecoder('utf-8').decode(new Uint8Array([255, 255]))

第2部分:UTF-8解码

0xFF不是UTF-8中的有效代码序列,因此它将解码为错误。这导致REPLACEMENT CHARACTER(U + FFFD)。由于有两个0xFF字节,因此可以得到U + FFFD U + FFFD或:

""

第3部分:UTF-8编码

将U + FFFD编码为UTF-8,为您提供字节0xEF 0xBF 0xBD。所以用U + FFFD U + FFFD编码一个字符串会得到字节0xEF 0xBF 0xBD或十进制:239 191 189 239 191 189

......这正是你得到的结果。

所以这完全符合规定。

那么......问题是什么?

我的猜测是你假设你可以将任何字节编码成字符串。这不是文本编码的工作方式。文本编码定义了从字符串元素到字节序列的映射。

并非所有编码都可以表示字符串的所有元素,但UTF-8(和UTF-16)可以表示JavaScript字符串中可能出现的所有代码点。

但反过来是真的。并非所有字节序列都对应于字符。当发现无效字节序列时,会发生错误。默认情况下,TextDecoder API会生成替换字符(�U+ FFFD),但您可以使用fatal标志来使其抛出异常。