358

是否有一种普遍接受的技术可以有效地将 JavaScript 字符串转换为ArrayBuffers,反之亦然?具体来说,我希望能够将 ArrayBuffer 的内容写入localStorage并读回。

4

27 回答 27

227

2016 年更新- 五年过去了,现在规范中有新的方法(参见下面的支持),可以使用正确的编码在字符串和类型化数组之间进行转换。

文本编码器

TextEncoder代表:_

TextEncoder接口表示特定方法的编码器,即特定字符编码,例如utf-8iso-8859-2, koi8, cp1261, gbk, ...编码器将代码点流作为输入并发出字节流。

自上述内容编写以来的更改说明:(同上)

注意:Firefox、Chrome 和 Opera 曾经支持 utf-8 以外的编码类型(例如 utf-16、iso-8859-2、koi8、cp1261 和 gbk)。从 Firefox 48 [...]、Chrome 54 [...] 和 Opera 41 开始,除了 utf-8 之外没有其他编码类型可用,以符合规范。*

*)更新了规格(W3) 和此处(whatwg)。

创建实例后,TextEncoder它将接受一个字符串并使用给定的编码参数对其进行编码:

if (!("TextEncoder" in window)) 
  alert("Sorry, this browser does not support TextEncoder...");

var enc = new TextEncoder(); // always utf-8
console.log(enc.encode("This is a string converted to a Uint8Array"));

如果需要,您当然可以使用.buffer结果上的参数Uint8Array将底层转换ArrayBuffer为不同的视图。

只需确保字符串中的字符符合编码模式,例如,如果您在示例中使用 UTF-8 范围之外的字符,它们将被编码为两个字节而不是一个字节。

对于一般用途,您可以将 UTF-16 编码用于localStorage.

文本解码器

同样,相反的过程使用TextDecoder

TextDecoder接口表示特定方法的解码器,即特定字符编码,例如utf-8, iso-8859-2, koi8, cp1261, gbk, ... 解码器将字节流作为输入并发出代码点流。

所有可用的解码类型都可以在这里找到。

if (!("TextDecoder" in window))
  alert("Sorry, this browser does not support TextDecoder...");

var enc = new TextDecoder("utf-8");
var arr = new Uint8Array([84,104,105,115,32,105,115,32,97,32,85,105,110,116,
                          56,65,114,114,97,121,32,99,111,110,118,101,114,116,
                          101,100,32,116,111,32,97,32,115,116,114,105,110,103]);
console.log(enc.decode(arr));

MDN StringView 库

这些的替代方法是使用StringView(许可为 lgpl-3.0),其目标是:

  • 基于 JavaScript ArrayBuffer 接口为字符串创建一个类似 C 的接口(即字符代码数组 — JavaScript 中的 ArrayBufferView)
  • 创建一个高度可扩展的库,任何人都可以通过向对象 StringView.prototype 添加方法来扩展它
  • 为此类字符串对象(从现在开始:stringViews)创建一组方法,这些对象严格处理数字数组,而不是创建新的不可变 JavaScript 字符串
  • 使用 JavaScript 的默认 UTF-16 DOMStrings 以外的 Unicode 编码

提供更多的灵活性。但是,它需要我们在现代浏览器中内置TextEncoder/时链接或嵌入这个库。TextDecoder

支持

截至 2018 年 7 月:

TextEncoder(实验性,在标准轨道上)

 Chrome    | Edge      | Firefox   | IE        | Opera     | Safari
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |    19°    |     -     |     25    |     -

 Chrome/A  | Edge/mob  | Firefox/A | Opera/A   |Safari/iOS | Webview/A
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |    19°    |     ?     |     -     |     38

°) 18: Firefox 18 implemented an earlier and slightly different version
of the specification.

WEB WORKER SUPPORT:

Experimental, On Standard Track

 Chrome    | Edge      | Firefox   | IE        | Opera     | Safari
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |     20    |     -     |     25    |     -

 Chrome/A  | Edge/mob  | Firefox/A | Opera/A   |Safari/iOS | Webview/A
 ----------|-----------|-----------|-----------|-----------|-----------
     38    |     ?     |     20    |     ?     |     -     |     38

Data from MDN - `npm i -g mdncomp` by epistemex
于 2016-06-18T22:50:10.163 回答
188

尽管使用 Blob/FileReader 的 Dennis 和 genkev 解决方案有效,但我不建议采用这种方法。这是一个简单问题的异步方法,它比直接解决方案慢得多。我在 html5rocks 中发布了一个更简单且(更快)的解决方案: http ://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String

解决方案是:

function ab2str(buf) {
  return String.fromCharCode.apply(null, new Uint16Array(buf));
}

function str2ab(str) {
  var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
  var bufView = new Uint16Array(buf);
  for (var i=0, strLen=str.length; i<strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}

编辑:

Encoding API 有助于解决字符串转换问题。查看Jeff Posnik在 Html5Rocks.com 上对上述原始文章的回复。

摘抄:

Encoding API 使原始字节和原生 JavaScript 字符串之间的转换变得简单,无论您需要使用许多标准编码中的哪一种。

<pre id="results"></pre>

<script>
  if ('TextDecoder' in window) {
    // The local files to be fetched, mapped to the encoding that they're using.
    var filesToEncoding = {
      'utf8.bin': 'utf-8',
      'utf16le.bin': 'utf-16le',
      'macintosh.bin': 'macintosh'
    };

    Object.keys(filesToEncoding).forEach(function(file) {
      fetchAndDecode(file, filesToEncoding[file]);
    });
  } else {
    document.querySelector('#results').textContent = 'Your browser does not support the Encoding API.'
  }

  // Use XHR to fetch `file` and interpret its contents as being encoded with `encoding`.
  function fetchAndDecode(file, encoding) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', file);
    // Using 'arraybuffer' as the responseType ensures that the raw data is returned,
    // rather than letting XMLHttpRequest decode the data first.
    xhr.responseType = 'arraybuffer';
    xhr.onload = function() {
      if (this.status == 200) {
        // The decode() method takes a DataView as a parameter, which is a wrapper on top of the ArrayBuffer.
        var dataView = new DataView(this.response);
        // The TextDecoder interface is documented at http://encoding.spec.whatwg.org/#interface-textdecoder
        var decoder = new TextDecoder(encoding);
        var decodedString = decoder.decode(dataView);
        // Add the decoded file's text to the <pre> element on the page.
        document.querySelector('#results').textContent += decodedString + '\n';
      } else {
        console.error('Error while requesting', file, this);
      }
    };
    xhr.send();
  }
</script>
于 2012-06-15T22:17:41.560 回答
91

您可以使用TextEncoderTextDecoderfrom the Encoding standard,由stringencoding library填充,将字符串转换为 ArrayBuffers 和从 ArrayBuffers 转换:

var uint8array = new TextEncoder().encode(string);
var string = new TextDecoder(encoding).decode(uint8array);
于 2012-07-10T10:30:22.357 回答
46

Blob 比 Blob 慢得多String.fromCharCode(null,array);

但如果数组缓冲区变得太大,则会失败。我发现的最佳解决方案是使用String.fromCharCode(null,array);并将其拆分为不会破坏堆栈但一次比单个字符快的操作。

大型数组缓冲区的最佳解决方案是:

function arrayBufferToString(buffer){

    var bufView = new Uint16Array(buffer);
    var length = bufView.length;
    var result = '';
    var addition = Math.pow(2,16)-1;

    for(var i = 0;i<length;i+=addition){

        if(i + addition > length){
            addition = length - i;
        }
        result += String.fromCharCode.apply(null, bufView.subarray(i,i+addition));
    }

    return result;

}

我发现这比使用 blob 快大约 20 倍。它也适用于超过 100mb 的大字符串。

于 2013-12-16T06:12:47.573 回答
24

根据 genkev 的回答,我为这两种方式创建了函数,因为BlobBuilder可以处理 String 和 ArrayBuffer:

function string2ArrayBuffer(string, callback) {
    var bb = new BlobBuilder();
    bb.append(string);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result);
    }
    f.readAsArrayBuffer(bb.getBlob());
}

function arrayBuffer2String(buf, callback) {
    var bb = new BlobBuilder();
    bb.append(buf);
    var f = new FileReader();
    f.onload = function(e) {
        callback(e.target.result)
    }
    f.readAsText(bb.getBlob());
}

一个简单的测试:

string2ArrayBuffer("abc",
    function (buf) {
        var uInt8 = new Uint8Array(buf);
        console.log(uInt8); // Returns `Uint8Array { 0=97, 1=98, 2=99}`

        arrayBuffer2String(buf, 
            function (string) {
                console.log(string); // returns "abc"
            }
        )
    }
)
于 2012-03-12T18:53:01.400 回答
18

以下所有内容都是关于从数组缓冲区中获取二进制字符串

我建议不要使用

var binaryString = String.fromCharCode.apply(null, new Uint8Array(arrayBuffer));

因为它

  1. 在大缓冲区上崩溃(有人写了关于 246300 的“魔术”大小,但我Maximum call stack size exceeded在 120000 字节缓冲区(Chrome 29)上出现错误)
  2. 的性能真的很差(见下文)

如果您确实需要同步解决方案,请使用类似

var
  binaryString = '',
  bytes = new Uint8Array(arrayBuffer),
  length = bytes.length;
for (var i = 0; i < length; i++) {
  binaryString += String.fromCharCode(bytes[i]);
}

它和前一个一样慢,但工作正常。在撰写本文时,似乎还没有针对该问题的快速同步解决方案(本主题中提到的所有库都对其同步功能使用相同的方法)。

但我真正推荐的是使用Blob+FileReader方法

function readBinaryStringFromArrayBuffer (arrayBuffer, onSuccess, onFail) {
  var reader = new FileReader();
  reader.onload = function (event) {
    onSuccess(event.target.result);
  };
  reader.onerror = function (event) {
    onFail(event.target.error);
  };
  reader.readAsBinaryString(new Blob([ arrayBuffer ],
    { type: 'application/octet-stream' }));
}

唯一的缺点(不是全部)是它是异步的。它比以前的解决方案快 8-10 倍!(一些细节:我的环境中的同步解决方案对于 2.4Mb 缓冲区需要 950-1050 毫秒,但对于相同数量的数据,使用 FileReader 的解决方案的时间约为 100-120 毫秒。我已经在 100Kb 缓冲区上测试了这两种同步解决方案,他们已经采取了几乎在同一时间,所以循环使用“应用”并不会慢很多。)

顺便说一句:How to convert ArrayBuffer to and from String作者比较像我这样的两种方法并得到完全相反的结果(他的测试代码在这里)为什么结果如此不同?可能是因为他的测试字符串是 1Kb 长(他称之为“veryLongStr”)。我的缓冲区是一个非常大的 JPEG 图像,大小为 2.4Mb。

于 2013-09-05T19:13:19.950 回答
18

如果字符串中有二进制数据(从nodejs+readFile(..., 'binary')cypress+cy.fixture(..., 'binary')等获得),则不能使用TextEncoder. 它仅支持utf8. 带有值>= 128的字节每个都变成 2 个字节。

ES2015:

a = Uint8Array.from(s, x => x.charCodeAt(0))

Uint8Array(33) [2, 134, 140, 186, 82, 70, 108, 182, 233, 40, 143, 247, 29, 76, 245, 206, 29, 87, 48, 160, 78, 225, 242 , 56, 236, 201, 80, 80, 152, 118, 92, 144, 48

s = String.fromCharCode.apply(null, a)

"ºRFl¶é(÷LõÎW0 Náò8ìÉPPv\0"

于 2017-08-16T19:58:12.693 回答
16

与这里的解决方案不同,我需要在 UTF-8 数据之间进行转换。为此,我使用 (un)escape/(en)decodeURIComponent 技巧编写了以下两个函数。它们非常浪费内存,分配了编码 utf8 字符串长度的 9 倍,尽管这些应该由 gc 恢复。只是不要将它们用于 100mb 的文本。

function utf8AbFromStr(str) {
    var strUtf8 = unescape(encodeURIComponent(str));
    var ab = new Uint8Array(strUtf8.length);
    for (var i = 0; i < strUtf8.length; i++) {
        ab[i] = strUtf8.charCodeAt(i);
    }
    return ab;
}

function strFromUtf8Ab(ab) {
    return decodeURIComponent(escape(String.fromCharCode.apply(null, ab)));
}

检查它是否有效:

strFromUtf8Ab(utf8AbFromStr('latinкирилицаαβγδεζηあいうえお'))
-> "latinкирилицаαβγδεζηあいうえお"
于 2013-09-10T15:21:11.023 回答
13

更新请参阅此答案的第二部分,我(希望)在其中提供了更完整的解决方案。)

我也遇到了这个问题,以下在 FF 6 中对我有用(对于一个方向):

var buf = new ArrayBuffer( 10 );
var view = new Uint8Array( buf );
view[ 3 ] = 4;
alert(Array.prototype.slice.call(view).join(""));

当然,不幸的是,您最终会得到数组中值的 ASCII 文本表示,而不是字符。不过,它仍然(应该)比循环更有效。例如。对于上面的示例,结果是0004000000,而不是几个空字符和一个 chr(4)。

编辑:

在查看MDC here之后,您可以创建一个ArrayBufferfrom an Array,如下所示:

var arr = new Array(23);
// New Uint8Array() converts the Array elements
//  to Uint8s & creates a new ArrayBuffer
//  to store them in & a corresponding view.
//  To get at the generated ArrayBuffer,
//  you can then access it as below, with the .buffer property
var buf = new Uint8Array( arr ).buffer;

要回答您的原始问题,这允许您转换ArrayBuffer<->String如下:

var buf, view, str;
buf = new ArrayBuffer( 256 );
view = new Uint8Array( buf );

view[ 0 ] = 7; // Some dummy values
view[ 2 ] = 4;

// ...

// 1. Buffer -> String (as byte array "list")
str = bufferToString(buf);
alert(str); // Alerts "7,0,4,..."

// 1. String (as byte array) -> Buffer    
buf = stringToBuffer(str);
alert(new Uint8Array( buf )[ 2 ]); // Alerts "4"

// Converts any ArrayBuffer to a string
//  (a comma-separated list of ASCII ordinals,
//  NOT a string of characters from the ordinals
//  in the buffer elements)
function bufferToString( buf ) {
    var view = new Uint8Array( buf );
    return Array.prototype.join.call(view, ",");
}
// Converts a comma-separated ASCII ordinal string list
//  back to an ArrayBuffer (see note for bufferToString())
function stringToBuffer( str ) {
    var arr = str.split(",")
      , view = new Uint8Array( arr );
    return view.buffer;
}

为方便起见,这里是function用于将原始 Unicode 转换StringArrayBuffer(仅适用于 ASCII/单字节字符)

function rawStringToBuffer( str ) {
    var idx, len = str.length, arr = new Array( len );
    for ( idx = 0 ; idx < len ; ++idx ) {
        arr[ idx ] = str.charCodeAt(idx) & 0xFF;
    }
    // You may create an ArrayBuffer from a standard array (of values) as follows:
    return new Uint8Array( arr ).buffer;
}

// Alerts "97"
alert(new Uint8Array( rawStringToBuffer("abc") )[ 0 ]);

以上允许您从ArrayBuffer-> String&ArrayBuffer再次返回,字符串可能存储在例如。.localStorage:)

希望这可以帮助,

于 2011-08-24T23:29:27.903 回答
7

我发现这种方法存在问题,主要是因为我试图将输出写入文件并且它没有正确编码。由于 JS 似乎使用 UCS-2 编码(sourcesource),我们需要进一步扩展这个解决方案,这是我的增强解决方案,适用于我。

我对通用文本没有任何困难,但是当它是阿拉伯文或韩文时,输出文件没有所有字符,而是显示错误字符

文件输出: ","10k unit":"",Follow:"Õ©íüY‹","Follow %{screen_name}":"%{screen_name}U“’Õ©íü",Tweet:"ĤüÈ","Tweet %{hashtag}":"%{hashtag} ’ĤüÈY‹","Tweet to %{name}":"%{name}U“xĤüÈY‹"},ko:{"%{followers_count} followers":"%{followers_count}…X \Ì","100K+":"100Ì tÁ","10k unit":"Ì è",Follow:"\°","Follow %{screen_name}":"%{screen_name} Ø \°X0",K:"œ",M:"1Ì",Tweet:"¸","Tweet %{hashtag}":"%{hashtag}

原来的: ","10k unit":"万",Follow:"フォローする","Follow %{screen_name}":"%{screen_name}さんをフォロー",Tweet:"ツイート","Tweet %{hashtag}":"%{hashtag} をツイートする","Tweet to %{name}":"%{name}さんへツイートする"},ko:{"%{followers_count} followers":"%{followers_count}명의 팔로워","100K+":"100만 이상","10k unit":"만 단위",Follow:"팔로우","Follow %{screen_name}":"%{screen_name} 님 팔로우하기",K:"천",M:"백만",Tweet:"트윗","Tweet %{hashtag}":"%{hashtag}

我从丹尼斯的解决方案和我找到的这篇文章中获取了信息。

这是我的代码:

function encode_utf8(s) {
  return unescape(encodeURIComponent(s));
}

function decode_utf8(s) {
  return decodeURIComponent(escape(s));
}

 function ab2str(buf) {
   var s = String.fromCharCode.apply(null, new Uint8Array(buf));
   return decode_utf8(decode_utf8(s))
 }

function str2ab(str) {
   var s = encode_utf8(str)
   var buf = new ArrayBuffer(s.length); 
   var bufView = new Uint8Array(buf);
   for (var i=0, strLen=s.length; i<strLen; i++) {
     bufView[i] = s.charCodeAt(i);
   }
   return bufView;
 }

这使我可以将内容保存到文件中而不会出现编码问题。

它是如何工作的:它基本上采用组成 UTF-8 字符的单个 8 字节块并将它们保存为单个字符(因此以这种方式构建的 UTF-8 字符可以由这些字符中的 1-4 个组成)。UTF-8 以长度为 1 到 4 个字节的格式对字符进行编码。我们在这里所做的是将字符串编码到一个 URI 组件中,然后将该组件转换为相应的 8 字节字符。这样我们就不会丢失长度超过 1 个字节的 UTF8 字符给出的信息。

于 2014-07-03T19:53:45.330 回答
6

如果您使用巨大的数组示例arr.length=1000000 ,您可以使用此代码来避免堆栈回调问题

function ab2str(buf) {
var bufView = new Uint16Array(buf);
var unis =""
for (var i = 0; i < bufView.length; i++) {
    unis=unis+String.fromCharCode(bufView[i]);
}
return unis
}

从顶部反转功能 mangini 答案

function str2ab(str) {
    var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
    var bufView = new Uint16Array(buf);
    for (var i=0, strLen=str.length; i<strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}
于 2016-01-06T11:47:03.423 回答
6

只是

const buffer = thisReturnsBuffers();

const blob = new Blob([buffer], {type: 'text/plain; charset=utf-8'});

blob.text().then(text => console.log(text));

或者

const stringVal = "string here";

const blob = new Blob([stringVal], {type: 'text/plain; charset=utf-8'});

blob.arrayBuffer().then(buffer => console.log(buffer));

为什么你们都把事情搞得这么复杂?

于 2021-06-08T09:27:13.030 回答
4

好吧,这是做同样事情的一种有点复杂的方式:

var string = "Blah blah blah", output;
var bb = new (window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder)();
bb.append(string);
var f = new FileReader();
f.onload = function(e) {
  // do whatever
  output = e.target.result;
}
f.readAsArrayBuffer(bb.getBlob());

编辑: BlobBuilder 长期以来一直被弃用,取而代之的是 Blob 构造函数,当我第一次写这篇文章时,它并不存在。这是一个更新的版本。(是的,这一直是一种非常愚蠢的转换方式,但这只是为了好玩!)

var string = "Blah blah blah", output;
var f = new FileReader();
f.onload = function(e) {
  // do whatever
  output = e.target.result;
};
f.readAsArrayBuffer(new Blob([string]));
于 2012-01-29T02:44:35.587 回答
4
  stringToArrayBuffer(byteString) {
    var byteArray = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
      byteArray[i] = byteString.codePointAt(i);
    }
    return byteArray;
  }
  arrayBufferToString(buffer) {
    var byteArray = new Uint8Array(buffer);
    var byteString = '';
    for (var i = 0; i < byteArray.byteLength; i++) {
      byteString += String.fromCodePoint(byteArray[i]);
    }
    return byteString;
  }
于 2018-07-21T19:40:02.900 回答
4

对于 node.js 以及使用https://github.com/feross/buffer的浏览器

function ab2str(buf: Uint8Array) {
  return Buffer.from(buf).toString('base64');
}
function str2ab(str: string) {
  return new Uint8Array(Buffer.from(str, 'base64'))
}

注意:这里的解决方案对我不起作用。我需要支持 node.js 和浏览器,只需将 UInt8Array 序列化为字符串。我可以将它序列化为 number[] 但这会占用不必要的空间。使用该解决方案,我无需担心编码,因为它是 base64。以防其他人遇到同样的问题......我的两分钱

于 2019-09-07T14:09:06.763 回答
3

在使用 mangini 的从转换为的解决方案之后ArrayBuffer- Stringab2str这是我发现的最优雅和最有用的解决方案 - 谢谢!),我在处理大型数组时遇到了一些问题。更具体地说,调用String.fromCharCode.apply(null, new Uint16Array(buf));会引发错误:

arguments array passed to Function.prototype.apply is too large.

为了解决它(绕过),我决定ArrayBuffer分块处理输入。所以修改后的解决方案是:

function ab2str(buf) {
   var str = "";
   var ab = new Uint16Array(buf);
   var abLen = ab.length;
   var CHUNK_SIZE = Math.pow(2, 16);
   var offset, len, subab;
   for (offset = 0; offset < abLen; offset += CHUNK_SIZE) {
      len = Math.min(CHUNK_SIZE, abLen-offset);
      subab = ab.subarray(offset, offset+len);
      str += String.fromCharCode.apply(null, subab);
   }
   return str;
}

块大小设置为,2^16因为这是我发现在我的开发环境中工作的大小。设置更高的值会导致相同的错误再次发生。可以通过将CHUNK_SIZE变量设置为不同的值来更改它。有一个偶数很重要。

性能注意事项 - 我没有对此解决方案进行任何性能测试。但是,由于它基于以前的解决方案,并且可以处理大型数组,我看不出为什么不使用它。

于 2014-01-19T08:50:13.543 回答
3

假设您有一个 arrayBuffer binaryStr:

let text = String.fromCharCode.apply(null, new Uint8Array(binaryStr));

然后将文本分配给状态。

于 2019-10-22T18:15:31.897 回答
3

以下是一个有效的Typescript实现:

bufferToString(buffer: ArrayBuffer): string {
    return String.fromCharCode.apply(null, Array.from(new Uint16Array(buffer)));
}

stringToBuffer(value: string): ArrayBuffer {
    let buffer = new ArrayBuffer(value.length * 2); // 2 bytes per char
    let view = new Uint16Array(buffer);
    for (let i = 0, length = value.length; i < length; i++) {
        view[i] = value.charCodeAt(i);
    }
    return buffer;
}

在使用crypto.subtle时,我已经将它用于许多操作。

于 2020-08-10T20:26:30.377 回答
2

参见此处:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView (基于 JavaScript ArrayBuffer 接口的字符串类 C 接口)

于 2013-06-12T16:14:54.280 回答
2

我使用了它并为我工作。

function arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}



function base64ToArrayBuffer(base64) {
    var binary_string =  window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array( len );
    for (var i = 0; i < len; i++)        {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}
于 2016-08-09T18:31:26.430 回答
2

atob() 返回的“本机”二进制字符串是一个每字符 1 字节的数组。

所以我们不应该将 2 个字节存储到一个字符中。

var arrayBufferToString = function(buffer) {
  return String.fromCharCode.apply(null, new Uint8Array(buffer));
}

var stringToArrayBuffer = function(str) {
  return (new Uint8Array([].map.call(str,function(x){return x.charCodeAt(0)}))).buffer;
}
于 2017-01-10T12:58:32.897 回答
1

是的:

const encstr = (`TextEncoder` in window) ? new TextEncoder().encode(str) : Uint8Array.from(str, c => c.codePointAt(0));
于 2018-01-23T09:23:35.257 回答
0

我建议不要使用 BlobBuilder 等已弃用的 API

BlobBuilder 早已被 Blob 对象弃用。将 Dennis 的答案中的代码(使用 BlobBuilder 的地方)与下面的代码进行比较:

function arrayBufferGen(str, cb) {

  var b = new Blob([str]);
  var f = new FileReader();

  f.onload = function(e) {
    cb(e.target.result);
  }

  f.readAsArrayBuffer(b);

}

请注意,与不推荐使用的方法相比,这更清洁、更不臃肿......是的,这绝对是这里要考虑的事情。

于 2014-05-22T15:30:40.220 回答
0

来自 emscripten:

function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
  if (!(maxBytesToWrite > 0)) return 0;
  var startIdx = outIdx;
  var endIdx = outIdx + maxBytesToWrite - 1;
  for (var i = 0; i < str.length; ++i) {
    var u = str.charCodeAt(i);
    if (u >= 55296 && u <= 57343) {
      var u1 = str.charCodeAt(++i);
      u = 65536 + ((u & 1023) << 10) | u1 & 1023
    }
    if (u <= 127) {
      if (outIdx >= endIdx) break;
      outU8Array[outIdx++] = u
    } else if (u <= 2047) {
      if (outIdx + 1 >= endIdx) break;
      outU8Array[outIdx++] = 192 | u >> 6;
      outU8Array[outIdx++] = 128 | u & 63
    } else if (u <= 65535) {
      if (outIdx + 2 >= endIdx) break;
      outU8Array[outIdx++] = 224 | u >> 12;
      outU8Array[outIdx++] = 128 | u >> 6 & 63;
      outU8Array[outIdx++] = 128 | u & 63
    } else {
      if (outIdx + 3 >= endIdx) break;
      outU8Array[outIdx++] = 240 | u >> 18;
      outU8Array[outIdx++] = 128 | u >> 12 & 63;
      outU8Array[outIdx++] = 128 | u >> 6 & 63;
      outU8Array[outIdx++] = 128 | u & 63
    }
  }
  outU8Array[outIdx] = 0;
  return outIdx - startIdx
}

像这样使用:

stringToUTF8Array('abs', new Uint8Array(3), 0, 4);
于 2020-10-09T09:34:10.137 回答
0

最近我也需要为我的一个项目做这个,所以做了一个很好的研究,并从谷歌的开发者社区得到了一个结果,它以一种简单的方式说明了这一点:

对于 ArrayBuffer 到字符串

function ab2str(buf) {
  return String.fromCharCode.apply(null, new Uint16Array(buf));
}
// Here Uint16 can be different like Uinit8/Uint32 depending upon your buffer value type.

对于字符串到 ArrayBuffer

function str2ab(str) {
  var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
  var bufView = new Uint16Array(buf);
  for (var i=0, strLen=str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}
//Same here also for the Uint16Array.

有关更多详细参考,您可以参考Google 的此博客

于 2021-01-02T15:30:22.093 回答
-1
var decoder = new TextDecoder ();
var string = decoder.decode (arrayBuffer);

请参阅https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode

于 2015-03-31T10:54:11.003 回答
-1

ArrayBuffer-> Buffer->String(Base64)

更改ArrayBufferBuffer,然后更改为String

Buffer.from(arrBuffer).toString("base64");
于 2021-09-04T07:11:14.093 回答