【问题标题】:UTF-32 decoding in ECMAScriptECMAScript 中的 UTF-32 解码
【发布时间】:2021-02-18 18:33:29
【问题描述】:

我有 UTF-32 数据,一个数组缓冲区。我需要将其转换为 ECMAScript 字符串。

有人告诉我,我可以将 TextDecoder 与 UTF-8 一起使用,而且它应该“正常工作”,我非常怀疑告诉我这个的人,但它仍然有效。

除了...输出文本充满了空字符(每个字符 3 个),因为将空字节填充读取为空字符,而不是将整个四个字节作为一个字符读取。 前任:
\x70\x00\x00\x00
成为
PUTF-32;空填充被读取为一个字符
P\0\0\0UTF-8;分开

根据 whatwg 编码规范,UTF-32 没有定义为要使用的编码标签,而是只有 UTF-8 和 UTF-16,而不是 UTF-32,有没有人对我如何可以在浏览器中实现正确的 UTF-32 解码吗?

说清楚,我关心的是现代浏览器,所以不包括IE、Amaya、Android Webview、Netscape Navigator等。

【问题讨论】:

  • 输入字节是 little-endian UTF-32 还是 Uint32Array(取决于平台)字节序?
  • 此库支持从 utf-32 转换:github.com/ashtuchkin/iconv-lite。它也适用于浏览器。
  • 最坏的情况,你看看空值是什么样子的,所以你可以自己做一个渲染函数
  • 例如:function renderData(da){return(da.split(`\\0`).join(``))}
  • @Ry- 现在,至于数据的字节序,我确信它是小字节序。给出的示例没有显示数据的字节序吗?如果有帮助的话,它是一个 Wasm 数据部分,所以我相信它不会依赖于平台,因为数据是硬编码到其中的,但我不确定浏览器如何处理它。

标签: javascript utf-32


【解决方案1】:

将其解码为 UTF-8 绝对是错误的!正如你所发现的。除了 NUL 之外,它将无法完全解码 ASCII 以外的字符。

您可以使用DataView 逐个读取代码点进行解码:

const utf32Decode = bytes => {
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
  let result = '';
  
  for (let i = 0; i < bytes.length; i += 4) {
    result += String.fromCodePoint(view.getInt32(i, true));
  }
  
  return result;
};

const result = utf32Decode(new Uint8Array([0x70, 0x00, 0x00, 0x00]));
console.log(JSON.stringify(result));

由于getInt32(无效长度)和String.fromCodePoint(无效代码点),无效的 UTF-32 将引发错误。

【讨论】:

  • 是的,空字符不是主要问题,我可以很容易地过滤掉它们,我担心的是一些太大的字符根本无法正确解码。我正在考虑将其重写为输出 ASCII 而不是 UTF-32,但我以后可能需要一些更大的代码点,离开它可能会有所帮助。我现在就测试一下。
  • @JadenGarcia:如果你可以控制源代码,如何让它输出 UTF-8?这几乎是 标准编码。 TextDecoder 届时将是正确的:)
  • 嗯,是的,我控制着源代码,但是 UTF-8 是一种很难在编程时实际操作的编码。对数据的迭代不会像访问固定宽度的 32 位整数那样简单。而且我会失去随机访问。
  • 等等,String.fromCodePoint 不是只允许 UTF-16 代码点吗?因此,任何超过 0xfff 的代码点都应该抛出错误,除非我弄错了?
  • @JadenGarcia:那是String.fromCharCode
【解决方案2】:

使用这个库:https://github.com/ashtuchkin/iconv-lite。它使用 browserify 或 webpack 在浏览器中工作(虽然它很大)。

例子:

const iconv = require("iconv-lite")

const yourBuffer = // however you're getting your buffer

const str = iconv.decode(yourBuffer, "utf32");

【讨论】:

  • 我很欣赏这个建议,但它似乎针对 Node.js,浏览器包最大为“~180kb”。是的,我不必重新发明轮子,这是一个额外的好处,而且我确信它可以被剥离,但在我使用它之前我肯定需要查看源代码,这将是一个相当大的很多要审查。
  • @JadenGarcia 我主要只是发布它以防其他人将来发现这个问题。它是我发现的少数几个处理 utf32 的包之一。
猜你喜欢
  • 2013-04-21
  • 2012-07-23
  • 1970-01-01
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
  • 2017-06-20
  • 2016-05-21
  • 1970-01-01
相关资源
最近更新 更多