是否有一种普遍接受的技术可以有效地将JavaScript字符串转换为arraybuffer,反之亦然?具体来说,我希望能够将ArrayBuffer的内容写入localStorage,然后再将其读回来。
当前回答
var decoder = new TextDecoder ();
var string = decoder.decode (arrayBuffer);
参见https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode
其他回答
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实例后,它将接受一个字符串并使用给定的编码参数对其进行编码:
如果(!("TextEncoder"在窗口)) alert(“对不起,这个浏览器不支持TextEncoder…”); var enc = new TextEncoder();// always utf-8 console.log(内附。encode("这是一个转换为Uint8Array的字符串"));
当然,如果需要的话,你可以在结果的Uint8Array上使用.buffer参数来将底层的ArrayBuffer转换为不同的视图。
只需确保字符串中的字符符合编码模式,例如,如果在示例中使用UTF-8范围之外的字符,它们将被编码为两个字节而不是一个字节。
一般情况下,你可以使用UTF-16编码来处理localStorage之类的东西。
TextDecoder
同样,相反的进程使用TextDecoder:
TextDecoder接口表示特定方法的解码器, 这是一种特定的字符编码,如utf-8, iso-8859-2, koi8, Cp1261, gbk,…解码器接受字节流作为输入并发出 代码点流。
所有可用的解码类型都可以在这里找到。
如果(!(“TextDecoder”在窗口)) alert(“抱歉,这个浏览器不支持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、65114114、97121、99111110118101114116, 101100, 32116111, 97, 32115116114105110103]); console.log (enc.decode (arr));
MDN StringView库
另一种选择是使用StringView库(许可为lgpl-3.0),其目标是:
to create a C-like interface for strings (i.e., an array of character codes — an ArrayBufferView in JavaScript) based upon the JavaScript ArrayBuffer interface to create a highly extensible library that anyone can extend by adding methods to the object StringView.prototype to create a collection of methods for such string-like objects (since now: stringViews) which work strictly on arrays of numbers rather than on creating new immutable JavaScript strings to work with Unicode encodings other than JavaScript's default 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
(更新请参阅这个答案的后半部分,我(希望)提供了一个更完整的解决方案。)
我也遇到了这个问题,以下是我在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,你可以从一个数组创建一个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;
}
为了方便起见,这里有一个将原始Unicode字符串转换为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:)
希望这能有所帮助,
Dan
var decoder = new TextDecoder ();
var string = decoder.decode (arrayBuffer);
参见https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode
好吧,这里有一种有点复杂的方式来做同样的事情:
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]));
如果你在字符串中有二进制数据(从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、152、118、92、144、48]
s = String.fromCharCode.apply(null, a)
“ºRFl¶é(÷LõÎW0 Náò8ìÉPPv\0”
推荐文章
- 在数组中获取所有选中的复选框
- 如何为Firebase构建云函数,以便从多个文件部署多个函数?
- 如何发送推送通知到web浏览器?
- AngularJS:工厂和服务?
- js:将一个组件包装成另一个组件
- 父ng-repeat从子ng-repeat的访问索引
- JSHint和jQuery: '$'没有定义
- 模仿JavaScript中的集合?
- 用JavaScript验证电话号码
- 如何在HTML5中改变视频的播放速度?
- 谷歌地图API v3:我可以setZoom后fitBounds?
- ES6/2015中的null安全属性访问(和条件赋值)
- 与push()相反;
- JS字符串“+”vs concat方法
- AngularJS使用ng-class切换类