Uint8Array 到 Javascript 中的字符串

IT技术 javascript
2021-02-05 13:32:04

我有一些 UTF-8 编码的数据存在于 Javascript 中的一系列 Uint8Array 元素中。有没有一种有效的方法可以将这些解码为常规的 javascript 字符串(我相信 Javascript 使用 16 位 Unicode)?我不想在当时添加一个字符,因为字符串连接会占用 CPU。

6个回答

TextEncoderTextDecoder根据stringencoding 库填充编码标准在字符串和 ArrayBuffers 之间进行转换:

var uint8array = new TextEncoder().encode("¢");
var string = new TextDecoder().decode(uint8array);
我认为现在最好的polyfillFastestSmallestTextEncoderDecoder,正如MDN 网站所推荐的那样
2021-03-15 13:32:04
nodejs.org/api/string_decoder.html来自示例: const { StringDecoder } = require('string_decoder'); const 解码器 = new StringDecoder('utf8'); const cent = Buffer.from([0xC2, 0xA2]); console.log(decoder.write(cent));
2021-03-21 13:32:04
对于像我这样懒惰的人npm install text-encoding,,var textEncoding = require('text-encoding'); var TextDecoder = textEncoding.TextDecoder;不用了,谢谢。
2021-03-27 13:32:04
当心 npm 文本编码库,webpack 包分析器显示该库很大
2021-04-04 13:32:04
请注意,Node.js在 v11 中添加了TextEncoder/ TextDecoderAPI,因此如果您仅针对当前的 Node 版本,则无需安装任何额外的包。
2021-04-10 13:32:04

这应该有效:

// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt

/* utf.js - UTF-8 <=> UTF-16 convertion
 *
 * Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
 * Version: 1.0
 * LastModified: Dec 25 1999
 * This library is free.  You can redistribute it and/or modify it.
 */

function Utf8ArrayToStr(array) {
    var out, i, len, c;
    var char2, char3;

    out = "";
    len = array.length;
    i = 0;
    while(i < len) {
    c = array[i++];
    switch(c >> 4)
    { 
      case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
        // 0xxxxxxx
        out += String.fromCharCode(c);
        break;
      case 12: case 13:
        // 110x xxxx   10xx xxxx
        char2 = array[i++];
        out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
        break;
      case 14:
        // 1110 xxxx  10xx xxxx  10xx xxxx
        char2 = array[i++];
        char3 = array[i++];
        out += String.fromCharCode(((c & 0x0F) << 12) |
                       ((char2 & 0x3F) << 6) |
                       ((char3 & 0x3F) << 0));
        break;
    }
    }

    return out;
}

它比其他解决方案更简洁,因为它不使用任何 hacks 也不依赖于浏览器 JS 功能,例如也适用于其他 JS 环境。

查看JSFiddle 演示

另请参阅相关问题:此处此处

问题是如何在没有字符串连接的情况下做到这一点
2021-03-13 13:32:04
为什么排除第 8、9、10 和 11 种情况?有什么特别的原因吗?情况 15 也是可能的,对吧?15(1111) 表示使用了 4 个字节,不是吗?
2021-03-14 13:32:04
这似乎有点慢。但我发现宇宙中唯一有效的片段。很好的发现+采用!
2021-03-24 13:32:04
我不明白为什么这没有更多的赞成票。通过 UTF-8 约定来处理小片段似乎非常明智。正如其他人指出的那样,Async Blob + Filereader 非常适合大文本。
2021-03-28 13:32:04
效果很好,除了它不处理 4+ 字节序列,例如fromUTF8Array([240,159,154,133])结果为空 (while fromUTF8Array([226,152,131])→"☃")
2021-04-04 13:32:04

这是我使用的:

var str = String.fromCharCode.apply(null, uint8Arr);
如果您将大型 Uint8Arrays 转换为二进制字符串并出现 RangeError,请参阅stackoverflow.com/a/12713326/471341 中的 Uint8ToString 函数
2021-03-13 13:32:04
SCRIPT28: Out of stack space当我输入 300+k 个字符或RangeErrorChrome 39时,IE 11 会抛出。Firefox 33 没问题。100+k 三个都运行正常。
2021-03-25 13:32:04
doc来看,这似乎无法解码 UTF8。
2021-03-30 13:32:04
这将抛出RangeError更大的文本。“已超出最大调用堆栈大小”
2021-04-06 13:32:04
这不会从en.wikipedia.org/wiki/UTF-8上的示例 unicode 字符产生正确的结果例如 String.fromCharCode.apply(null, new Uint8Array([0xc2, 0xa2])) 不会产生 ¢。
2021-04-10 13:32:04

在 Node 中,“Buffer实例也是Uint8Array实例”,所以buf.toString()在这种情况下有效。

这在 Chrome 中不起作用。 Buffer是 nodejs
2021-03-13 13:32:04
对我很有用。如此简单!但实际上Uint8Array有 toString() 方法。
2021-04-02 13:32:04
简洁大方,没想到Buffer也是Uint8Array。谢谢!
2021-04-05 13:32:04
@doom 在浏览器端, Uint8Array.toString() 不会编译 utf-8 字符串,它会列出数组中的数值。因此,如果您拥有的是来自另一个来源的 Uint8Array 并且碰巧也不是 Buffer,则您需要创建一个来实现魔法:Buffer.from(uint8array).toString('utf-8')
2021-04-05 13:32:04
“Buffer.prototype.toString.call(uint8array, 'utf8')”如何避免创建新的缓冲区实例。
2021-04-05 13:32:04

可在 Chrome 示例应用程序之一中找到,尽管这适用于可以进行异步转换的较大数据块。

/**
 * Converts an array buffer to a string
 *
 * @private
 * @param {ArrayBuffer} buf The buffer to convert
 * @param {Function} callback The function to call when conversion is complete
 */
function _arrayBufferToString(buf, callback) {
  var bb = new Blob([new Uint8Array(buf)]);
  var f = new FileReader();
  f.onload = function(e) {
    callback(e.target.result);
  };
  f.readAsText(bb);
}
正如您所说,除非要转换的缓冲区真的非常大,否则这会表现得非常糟糕。例如,在 V8 中实现的简单字符串(比如 10-40 字节)的同步 UTF-8 到 wchar 转换应该远小于一微秒,而我猜你的代码需要数百倍。谢谢都一样。
2021-04-04 13:32:04