【浏览器怎么操作二进制】【二】文本的二进制数据编解码

TextDecoder 和 TextEncoder

背景知识

  • ArrayBufferView 是所有视图的总称。
  • BufferSourceArrayBufferArrayBufferView 的总称。

本章中学习这些术语。BufferSource 是最常用的术语之一,因为它的意思是“任何类型的二进制数据” —— ArrayBuffer 或其上的视图。

如果二进制数据实际上是一个字符串怎么办?例如,我们收到了一个包含文本数据的文件。

内建的 TextDecoder 对象在给定缓冲区(buffer)和编码格式(encoding)的情况下,能够将值读取到实际的 JavaScript 字符串中。

首先我们需要创建:

1
let decoder = new TextDecoder([label], [options]);
  • label —— 编码格式,默认为 utf-8,但同时也支持 big5windows-1251 等许多其他编码格式。
  • options —— 可选对象:
    • fatal —— 布尔值,如果为 true 则为无效(不可解码)字符抛出异常,否则(默认)用字符 \uFFFD 替换无效字符。
    • ignoreBOM —— 布尔值,如果为 true 则 BOM(可选的字节顺序 unicode 标记),很少需要使用。(这是啥)(MDN 布尔值,是否忽略 BOM(byte order marker)标记。)

……然后解码:

1
let str = decoder.decode([input], [options]);
  • input —— 要被解码的 BufferSource

  • options

    —— 可选对象:

    • stream —— 对于解码流,为 true,则将传入的数据块(chunk)作为参数重复调用 decoder。在这种情况下,多字节的字符可能偶尔会在块与块之间被分割。这个选项告诉 TextDecoder 记住“未完成”的字符,并在下一个数据块来的时候进行解码。

    (意思是传入的 BufferSource 是一块一块的)

1
2
3
let uint8Array = new Uint8Array([72, 101, 108, 108, 111]);

alert(new TextDecoder().decode(uint8Array)); // Hello
1
2
3
let uint8Array = new Uint8Array([228, 189, 160, 229, 165, 189]);

alert(new TextDecoder().decode(uint8Array)); // 你好

我们可以通过为其创建子数组视图来解码部分缓冲区:

1
2
3
4
5
6
7
let uint8Array = new Uint8Array([0, 72, 101, 108, 108, 111, 0]);

// 该字符串位于中间
// 在不复制任何内容的前提下,创建一个新的视图
let binaryString = uint8Array.subarray(1, -1);

alert(new TextDecoder().decode(binaryString)); // Hello

TextEncoder

TextEncoder 做相反的事情 —— 将字符串转换为字节。

语法为:

1
let encoder = new TextEncoder();

只支持 utf-8 编码。

它有两种方法:

  • encode(str) —— 从字符串返回 Uint8Array
  • encodeInto(str, destination) —— 将 str 编码到 destination 中,该目标必须为 Uint8Array
1
2
3
4
let encoder = new TextEncoder();

let uint8Array = encoder.encode("Hello");
alert(uint8Array); // 72,101,108,108,111

MDN 例子

1
2
3
4
5
const encoder = new TextEncoder();
const array = encoder.encode("€"); // Uint8Array(3) [226, 130, 172]

const decoder = new TextDecoder();
const str = decoder.decode(array); // String "€"