JavaScript 在字符串与字节数组之间互相转换

JavaScript 目前没有一个标准的方法可以将字符串转换为 ArrayBuffer。网络上流传的一些方法不能完美的处理 Unicode ,以下是一些方法可以安全在字符串与字节数组之间互相转换。

使用 Encoding API

大家似乎都不知道在 Web 平台早就有处理文本编码的方法规范,Firefox 和 Chrome 都完美支持,速度和实现肯定是最快最正确的,不仅仅支持 Unicode 还可以处理 iso-8859-2koi8cp1261gbk 等其他编码格式。旧版本的 Edge 用不了很遗憾。

这里有一篇 来自 Google 的文章 介绍了如何使用 Encoding API 转换文本与 ArrayBuffer。

Encoding API 的兼容性表格

使用 Node Buffer 类

Node 没有 Encoding API ,我们可以使用 Buffer 类替代。

// String => Buffer
let buf = Buffer.from("𠀀")

// Buffer => String
buf.toString()

使用原生 JS 方法

如果你想写跨平台的代码,可以使用以下的方法。

inexorabletash / text-encoding

这是一个 Encoding API 的 Polyfill ,实现了大部分的功能。核心功能(99.1 KB) + 非 Unicode 编码支持(518 KB)体积实在有点大。

MDN 上提供的 TextEncoder Polyfill

代码还蛮长的我就不贴过来了。直接兼容到 IE5。因为是 MDN 提供的比较放心。

我自己写的字符串转 ArrayBuffer

使用的是 codePointAt() 方法,支持 ES6 的浏览器都可以用。IE 兼容没有 MDN 的好,但是结果还是正确的。

function textToArrayBuffer(s: string) {
  var i = s.length;
  var n = 0;
  var ba = new Array()
  for (var j = 0; j < i;) {
    var c = s.codePointAt(j);
    if (c < 128) {
      ba[n++] = c;
      j++;
    }
    else if ((c > 127) && (c < 2048)) {
      ba[n++] = (c >> 6) | 192;
      ba[n++] = (c & 63) | 128;
      j++;
    }
    else if ((c > 2047) && (c < 65536)) {
      ba[n++] = (c >> 12) | 224;
      ba[n++] = ((c >> 6) & 63) | 128;
      ba[n++] = (c & 63) | 128;
      j++;
    }
    else {
      ba[n++] = (c >> 18) | 240;
      ba[n++] = ((c >> 12) & 63) | 128;
      ba[n++] = ((c >> 6) & 63) | 128;
      ba[n++] = (c & 63) | 128;
      j+=2;
    }
  }
  return new Uint8Array(ba).buffer;
}

最后

如果你有其他好用的方法可以在评论里留言。经过测试以上所有方法都支持所有 Unicode 区域。

发表评论

电子邮件地址不会被公开。 必填项已用*标注