textencoder 仅支持 utf-8 编码,传入 "gbk" 或 "utf-16" 会抛 rangeerror;textdecoder 默认静默忽略非法 utf-8 字节,需设 { fatal: true } 才报错,且不支持自动编码识别。

TextEncoder 只能转 UTF-8,别想用它编码 GBK 或 UTF-16
浏览器原生 TextEncoder 严格限定为 UTF-8 编码,没有参数可选,传 "gbk" 或 "utf-16" 会直接抛错:RangeError: Unknown encoding: gbk。它不是 Node.js 的 Buffer.from(str, 'encoding'),也不支持编码自动探测——输入字符串是什么 Unicode 码点,就按 UTF-8 规则逐字节编码成 Uint8Array。
常见误用场景:想把中文表单内容转成 GBK 字节数组发给老后台。这时候必须换方案,比如用第三方库(如 iconv-lite)或后端中转。
-
new TextEncoder()构造时不接受任何参数,括号里填东西也无效 - 对 ASCII 字符(如
"hello"),输出的Uint8Array和 ASCII 字节一致;对中文(如"你好"),每个字符占 3 字节,共 6 字节 - 编码结果不含 BOM,
"\uFEFF"(即0xEF 0xBB 0xBF)需手动拼接(如果协议强制要求)
TextDecoder 解码失败时默认静默丢弃,得开 fatal 才报错
默认情况下,TextDecoder 遇到非法 UTF-8 字节序列(比如截断的多字节字符、乱码二进制)会跳过并继续解码,返回一个不完整或错乱的字符串,且不提示任何异常。这容易掩盖数据损坏问题。
要让错误暴露出来,必须显式启用 fatal 选项:
const decoder = new TextDecoder("utf-8", { fatal: true });
try {
decoder.decode(new Uint8Array([0xFF, 0xFE])); // 非法 UTF-8
} catch (e) {
// e 是 TypeError,message 包含 "The encoded data was not valid."
}
- 不设
{ fatal: true }时,decode()对非法输入返回空字符串或部分正确文本,极易引发后续逻辑 bug -
TextDecoder不支持自动编码识别,new TextDecoder()默认就是"utf-8",不能靠它猜 GBK 或 Shift-JIS - 若需处理可能混杂编码的数据,先用
TextEncoder原样保存原始字节,再交由专门的检测库(如jschardet)判断
跨平台读文件时,FileReader.readAsArrayBuffer() + TextDecoder 是安全组合
用户上传一个本地 .txt 文件,想读出文本内容,最稳妥路径是:用 FileReader 读成 ArrayBuffer,再用 TextDecoder 解码。绕过 readAsText()——因为后者依赖浏览器猜测编码,而猜测常出错(尤其非 UTF-8 文件)。
实操要点:
- 获取
file后,必须调用reader.readAsArrayBuffer(file),不是readAsText() - 解码前检查
ArrayBuffer是否为空(空文件或读取失败) - 明确指定编码:如服务端约定为 UTF-8,就用
new TextDecoder("utf-8");若不确定,至少加{ fatal: true }防止静默错误 - 注意
ArrayBuffer是只读的,TextDecoder.decode()接收的是视图(如new Uint8Array(buffer))或直接传buffer
Base64 转字符串别硬套 TextDecoder,先用 atob 再 new TextDecoder
有人看到 Base64 字符串(如 "5L2g5aW9"),想直接 decoder.decode(atob(str)) ——这会报错,因为 atob() 返回的是 DOMString(UTF-16 字符串),不是字节流。而 TextDecoder.decode() 要求输入是 ArrayBuffer 或 TypedArray。
正确做法是:先用 atob() 得到原始字符串,再用 TextEncoder 编回字节,最后交给 TextDecoder(看似绕,实为保真):
function base64ToUtf8String(base64) {
const binStr = atob(base64);
const bytes = new TextEncoder().encode(binStr); // 把每个字符当 Unicode 编成 UTF-8 字节
return new TextDecoder("utf-8").decode(bytes);
}
- 不能用
Uint8Array.from(binStr, c => c.charCodeAt(0))替代TextEncoder,因为那样得到的是 UTF-16 码元字节,不是 UTF-8 - 如果 Base64 原本就来自 UTF-8 字节(如后端
Buffer.from(str).toString('base64')),那上述转换才是等价的 - 前端生成 Base64 时,也应统一走
TextEncoder → ArrayBuffer → btoa链路,避免编码错位
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











