在字符串和ArrayBuffers之间转换

kpo*_*zin 231 javascript serialization typed-arrays arraybuffer

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

man*_*ini 171

尽管使用Blob/FileReader的Dennis和gengkev解决方案有效,但我不建议采用这种方法.它是一个简单问题的异步方法,它比直接解决方案慢得多.我在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;
}
Run Code Online (Sandbox Code Playgroud)

编辑:

编码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>
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是我对html5rocks的评论尚未获得批准.因此这里简短的回答.我仍然认为,这不是正确的方法,因为你错过了很多角色,特别是因为大多数页面都采用UTF-8编码.一方面,对于更多特殊字符(比方说亚洲字母),charCodeAt函数返回一个4字节值,因此它们将被切断.另一方面,简单的英文字符会使ArrayBuffer增长两次(每个1字节字符使用2个字节).想象一下,通过WebSocket发送英文文本,需要两次时间(实时环境不好). (16认同)
  • 三个例子:(1)`这是一个很酷的文本!`UTF8中的20字节 - Unicode中的40字节.(2)`UTF8中的6个字节 - Unicode中的6个字节.(3)`☐☑☒`以UTF8为单位的9字节 - Unicode中的6字节.如果要将字符串存储为UTF8文件(通过Blob和File Writer API),则不能使用这两种方法,因为ArrayBuffer将使用Unicode而不是UTF8. (8认同)
  • @jacob - 我认为错误是因为可以传递给apply()方法的数组长度有限制.例如`String.fromCharCode.apply(null,new Uint16Array(new ArrayBuffer(246300))).length`适用于Chrome,但是如果你使用246301,我会得到你的RangeError异常 (6认同)
  • @Dennis - JS字符串使用UCS2,而不是UTF8(甚至是UTF16) - 这意味着charCodeAt()总是返回0 - > 65535的值.任何需要4个字节结尾的UTF-8代码点都将用代理对表示(参见http:/ /en.wikipedia.org/wiki/UTF-16#Code_points_U.2B10000_to_U.2B10FFFF) - 即两个独立的16位UCS2值. (5认同)
  • 我收到一个错误:未捕获的RangeError:超出了最大调用堆栈大小.可能是什么问题呢? (3认同)

小智 95

更新2016 -五年现在有在规范的新方法(见下方支撑)使用正确的编码字符串和类型数组之间的转换.

TextEncoder

TextEncoder代表:

TextEncoder接口表示为具体的方法的编码器,这是一个特定的字符编码,如utf-8,iso-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"));
Run Code Online (Sandbox Code Playgroud)

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

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

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

TextDecoder

同样,相反的过程使用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));
Run Code Online (Sandbox Code Playgroud)

MDN StringView库

另一种方法是使用StringView(许可为lgpl-3.0),其目标是:

  • 基于JavaScript ArrayBuffer接口为字符串(即一个字符代码数组--JavaScript中的ArrayBufferView)创建类似C的接口
  • 创建一个高度可扩展的库,任何人都可以通过向对象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
Run Code Online (Sandbox Code Playgroud)

  • IE和Edge不支持TextDecoder:https://caniuse.com/#search=TextDecoder (2认同)
  • “TextEncoder”的问题在于,如果字符串中有二进制数据(例如图像),则您不想使用“TextEncoder”(显然)。代码点大于 127 的字符产生两个字节。为什么字符串中有二进制数据?`cy.fixture(NAME, 'binary')` (`cypress`) 生成一个字符串。 (2认同)

Ilm*_*nen 71

您可以使用TextEncoder,并TextDecoder编码标准,它是由polyfilled stringencoding库,以字符串转换为从ArrayBuffers:

var uint8array = new TextEncoder().encode(string);
var string = new TextDecoder(encoding).decode(uint8array);
Run Code Online (Sandbox Code Playgroud)

  • `npm install text-encoding`,`var textEncoding = require('text-encoding'); var TextDecoder = textEncoding.TextDecoder;`.不用了,谢谢. (5认同)
  • 这不适用于所有类型的字符。 (3认同)
  • 顺便说一下,默认情况下这在Firefox中可用:https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder.decode (2认同)
  • 这是正确的链接:https://github.com/inexorabletash/text-encoding (2认同)
  • 赞成新的API,它比怪异的解决方法好得多! (2认同)

Rya*_*ein 37

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

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

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

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;

}
Run Code Online (Sandbox Code Playgroud)

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

  • 我们应该采用这种解决方案.因为这解决了比被接受的用例多一个用例 (2认同)

Den*_*nis 21

根据gengkev的答案,我为这两种方法创建了函数,因为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());
}
Run Code Online (Sandbox Code Playgroud)

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());
}
Run Code Online (Sandbox Code Playgroud)

一个简单的测试:

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"
            }
        )
    }
)
Run Code Online (Sandbox Code Playgroud)

  • BlobBuilder在较新的浏览器中已被弃用.改变`new BlobBuilder(); bb.append(buf);`到`new Blob([buf])`,通过`new UintArray(buf)`(或任何适合底层数据类型的东西)将第二个函数中的ArrayBuffer强制转换为UintArray,然后摆脱`getBlob()`调用.最后,为了清洁,将bb重命名为blob,因为它不再是BlobBuilder. (17认同)

Sea*_*ris 20

只是

const buffer = thisReturnsBuffers();

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

blob.text().then(text => console.log(text));
Run Code Online (Sandbox Code Playgroud)

或者

const stringVal = "string here";

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

blob.arrayBuffer().then(buffer => console.log(buffer));
Run Code Online (Sandbox Code Playgroud)

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


Kon*_*nin 15

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

我建议不要使用

var binaryString = String.fromCharCode.apply(null, new Uint8Array(arrayBuffer));
Run Code Online (Sandbox Code Playgroud)

因为它

  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]);
}
Run Code Online (Sandbox Code Playgroud)

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

但我真正推荐的是使用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' }));
}
Run Code Online (Sandbox Code Playgroud)

唯一的缺点(并非全部)是它是异步的.它以前的解决方案快810倍!(一些细节:我的环境上的同步解决方案对于2.4Mb缓冲区需要950-1050毫秒,但对于相同数量的数据,使用FileReader的解决方案的时间大约为100-120毫秒.我已经测试 100Kb缓冲区上的两个同步解决方案差不多同一时间,所以循环使用'apply'的速度并不慢.)

BTW在这里:如何将ArrayBuffer转换为String作者和从作者转换比较像我这样的两种方法并获得完全相反的结果(他的测试代码在这里)为什么如此不同的结果?可能是因为他的测试字符串长达1Kb(他称之为"veryLongStr").我的缓冲区是一个非常大的JPEG图像,大小为2.4Mb.


Mos*_*hev 13

与此处的解决方案不同,我需要转换为/从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)));
}
Run Code Online (Sandbox Code Playgroud)

检查它是否有效:

strFromUtf8Ab(utf8AbFromStr('latin????????????????????'))
-> "latin????????????????????"
Run Code Online (Sandbox Code Playgroud)


Dan*_*ore 12

(更新请参阅本答复的下半部分,我希望(有希望)提供更完整的解决方案.)

我也遇到过这个问题,以下在FF 6中为我工作(一个方向):

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

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

编辑:

看后MDC 在这里,你可以创建一个ArrayBufferArray如下:

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;
Run Code Online (Sandbox Code Playgroud)

要回答您的原始问题,这允许您按如下方式转换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;
}
Run Code Online (Sandbox Code Playgroud)

为方便起见,这里有一个function用于将原始Unicode String转换为ArrayBuffer(仅适用于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 ]);
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助,

  • 使用base64编码怎么样? (2认同)

can*_*ero 11

对于 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'))
}
Run Code Online (Sandbox Code Playgroud)

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


Die*_*ito 7

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

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

文件输出: ","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;
 }
Run Code Online (Sandbox Code Playgroud)

这允许我将内容保存到文件而不会出现编码问题.

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


Elb*_*baz 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
}
Run Code Online (Sandbox Code Playgroud)

反向功能 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;
}
Run Code Online (Sandbox Code Playgroud)


小智 6

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

ES2015:

a = Uint8Array.from(s, x => x.charCodeAt(0))
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

“ºRFl¶é(÷LõÎW0Náò8ìÉPPv\ 0”


N-a*_*ate 6

以下是一个有效的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;
}
Run Code Online (Sandbox Code Playgroud)

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


gen*_*kev 5

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

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());
Run Code Online (Sandbox Code Playgroud)

编辑: BlobBuilder 早已被弃用,取而代之的是 Blob 构造函数,当我第一次写这篇文章时,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]));
Run Code Online (Sandbox Code Playgroud)


Bar*_*ear 5

最近,我也需要为我的一个项目执行此操作,因此进行了深入研究,并从 Google 开发者社区得到了一个结果,该结果以简单的方式说明了这一点:

对于 ArrayBuffer 到 String

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.
Run Code Online (Sandbox Code Playgroud)

对于字符串到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.
Run Code Online (Sandbox Code Playgroud)

如需更详细的参考,您可以参考Google 的此博客