字符串和arraybuffer之间的转换

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

580584 次浏览

(更新请参阅这个答案的后半部分,在那里我(希望)提供了一个更完整的解决方案。)

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

var buf = new ArrayBuffer( 10 );
var view = new Uint8Array( buf );
view[ 3 ] = 4;
alert(Array.prototype.slice.call(view).join(""));
当然,不幸的是,您最终得到的是数组中值的ASCII文本表示,而不是字符。尽管如此,它仍然(应该)比循环更有效。 如。对于上面的例子,结果是0004000000,而不是几个空字符&一杆(4). < / p >

编辑:

在查看争取民主变革运动 在这里之后,你可以从Array创建一个ArrayBuffer,如下所示:

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 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 ]);

上面允许你从ArrayBuffer -> String &再次返回ArrayBuffer,其中字符串可能存储在eg中。.localStorage:)

希望这能有所帮助,

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

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]));

基于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());
}

而且

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"
}
)
}
)
虽然Dennis和gengkev使用Blob/FileReader的解决方案有效,但我不建议采用这种方法。这是一种解决简单问题的异步方法,比直接解决方案要慢得多。我在html5rocks上发布了一个更简单(更快)的解决方案: http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String < / p >

解决方案是:

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;
}

编辑:

编码API有助于解决字符串转换问题。在Html5Rocks.com上查看杰夫Posnik对上述原始文章的响应。

摘录:

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>

你可以使用TextEncoderTextDecoder中的编码标准(由stringencoding图书馆填充)来转换字符串和arraybuffer:

var uint8array = new TextEncoder().encode(string);
var string = new TextDecoder(encoding).decode(uint8array);

请看这里:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView (一个基于JavaScript ArrayBuffer接口的类似c语言的字符串接口)

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

我建议不要用

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

因为它

  1. 崩溃在大缓冲区上(有人写了关于246300的“神奇”大小,但我在120000字节缓冲区上得到了Maximum call stack size exceeded错误(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倍然后以前的解决方案!(一些细节:在我的环境中,同步解决方案需要950-1050 ms才能获得2.4Mb的缓冲区,而使用FileReader的解决方案需要大约100-120 ms才能获得相同数量的数据。我已经在100Kb缓冲区上测试了这两个同步解决方案,它们几乎花费了相同的时间,所以使用'apply'的循环并不会慢很多。)

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

与这里的解决方案不同,我需要从UTF-8数据转换到UTF-8数据。为此,我使用(un)escape/(en)decodeURIComponent技巧编写了以下两个函数。它们非常浪费内存,分配的长度是编码后utf8-string的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кирилицаαβγδεζηあいうえお"

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;


}

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

在使用了mangini的从ArrayBuffer转换到String - ab2str的解决方案(这是我发现的最优雅和有用的解决方案-谢谢!)之后,我在处理大型数组时遇到了一些问题。更具体地说,调用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变量设置为不同的值来改变它。偶数是很重要的。

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

我不建议使用已弃用的api,如BlobBuilder

Blob对象早已弃用了BlobBuilder。比较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);


}

请注意,与已弃用的方法相比,这是多么干净和不那么臃肿……是的,这绝对是需要考虑的。

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

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

< >强文件输出: ”、“单位”:“10 K”:“O©iuY喜爱”、“遵循% % {screen_name} {screen_name}”:“U”“O©iu“推特:“¤问题”、“推%{标签}”:“%{标签}’一个¤uEY喜爱”,“推特%{名称}”:“%{名称}U”xA¤uEY喜爱”},柯:{“% {followers_count}的追随者”:“% {followers_count}…X \”,“100 K +”:“100我助教”,“10 K单位”:“我e”,遵循:“\°”,“跟着% {screen_name}”:“% {screen_name}Ø\°X0”,凯西:“œ”,男:“我”,推特:“¸”,“推特%{标签}”:“%{标签} < /代码> < / p >

< >强原: ”、“10 K单位”:“万”,:“フォローする”、“遵循% {screen_name}”:“% {screen_name}さんをフォロー”推特:“ツイート”、“推%{标签}”:“%{标签}をツイートする”、“推%{名称}”:“% {name}さんへツイートする”},柯:{“% {followers_count}的追随者”:“% {followers_count}명의팔로워”,“100 K +”:“100만이상”,“10 K单位”:“만단위”,遵循:“팔로우”,“跟着% {screen_name}”:“% {screen_name}님팔로우하기”,凯西:“천”,男:“백만”,推特:“트윗”,“推特%{标签}”:“%{标签} < /代码> < / p >

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

这是我的代码:

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组件中编码sting,然后将该组件转换为相应的8字节字符。这样我们就不会丢失长度超过1字节的UTF8字符所提供的信息

var decoder = new TextDecoder ();
var string = decoder.decode (arrayBuffer);

看到https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode

如果你使用大数组例子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
}
< p >反向功能 Mangini从上面回答 < / p >
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 -五年过去了,现在规范中有了新的方法(参见下面的支持),可以使用适当的编码在字符串和类型化数组之间进行转换。

TextEncoder

TextEncoder代表:

TextEncoder接口表示特定方法的编码器, 这是一个特定的字符编码,如utf-8iso-8859-2koi8, __abc0, __abc1,…编码器以码点流作为输入和

写完以上内容后,请注意:(如上)。

注意:Firefox, Chrome和Opera曾经支持编码 utf-8以外的类型(如utf-16、iso-8859-2、koi8、cp1261和 gbk)。Firefox 48[…]], Chrome 54[…]Opera 41,没有 为了匹配,除了utf-8,还有其他编码类型可用 规范。* < / p >

*) 更新的规格 (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"));

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

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

一般情况下,你可以使用UTF-16编码来处理localStorage之类的东西。

TextDecoder

同样,相反的进程使用TextDecoder:

TextDecoder接口表示特定方法的解码器, 这是一个特定的字符编码,比如utf-8iso-8859-2koi8, __abc0, __abc1,…解码器接受字节流作为输入并发出

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

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中的ArrayBufferView)创建一个类似c语言的接口 JavaScript ArrayBuffer接口
  • 创建一个高度可扩展的库,任何人都可以通过向StringView.prototype对象添加方法来扩展它
  • 来创建此类类字符串对象的方法集合(从现在开始:stringViews),这些方法严格处理数字数组 而不是创建新的不可变JavaScript字符串
  • 使用Unicode编码,而不是JavaScript默认的UTF-16 DOMStrings

给予更多的灵活性。然而,当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

我用了这个,对我很有用。

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;
}

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;
}

如果字符串中有二进制数据(从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)

“º采用树脂¶e(÷LoIW0 Nao8iEPPv \ 0”

是的:

const encstr = (`TextEncoder` in window) ? new TextEncoder().encode(str) : Uint8Array.from(str, c => c.codePointAt(0));
  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;
}

对于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到一个字符串。我可以将它序列化为一个数字[],但这会占用不必要的空间。有了这个解决方案,我不需要担心编码,因为它是base64。以防其他人也有同样的问题……我的意见

假设你有一个arrayBuffer binaryStr:

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

然后你把文本赋值给状态。

下面是一个工作的打印稿实现:

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时,我已经使用它进行了许多操作。

从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);

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

用于ArrayBuffer to 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.

用于字符串到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.

有关更详细的参考,您可以参考谷歌的这个博客

只是

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));

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

ArrayBufferBufferString(Base64)

ArrayBuffer改为Buffer,然后改为String

Buffer.from(arrBuffer).toString("base64");

使用splat unpacking代替loops:

arrbuf = new Uint8Array([104, 101, 108, 108, 111])
text = String.fromCharCode(...arrbuf)
console.log(text)

对于子字符串,可以使用arrbuf.slice()