javascript 如何将数组缓冲区转换为字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26754486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to convert arraybuffer to string
提问by Kapil
I have written a simple TCP server on node.js to send some data to a Chrome app. In the chrome app, when I get the data, I convert that to string using below function, I get an exception "byte length of Uint16Array should be a multiple of 2"
我在 node.js 上编写了一个简单的 TCP 服务器来将一些数据发送到 Chrome 应用程序。在 chrome 应用程序中,当我获取数据时,我使用下面的函数将其转换为字符串,我得到一个异常“ Uint16Array 的字节长度应该是 2 的倍数”
String.fromCharCode.apply(null, new Uint16Array(buffer))
I could not find any information about what could be causing this and how to fix this. Any pointers on this is highly appreciated.
我找不到有关可能导致此问题的原因以及如何解决此问题的任何信息。任何关于此的指针都受到高度赞赏。
Below is the code in node.js server for sending the data to client:
下面是 node.js 服务器中用于将数据发送到客户端的代码:
socket.on('data', function(data) {
console.log('DATA ' + socket.remoteAddress + ': ' + data);
// Write the data back to the socket,
// the client will receive it as data from the server
var r= socket.write('from server\r\n');
});
Below is the code from chrome app:
以下是来自 chrome 应用程序的代码:
chrome.sockets.tcp.onReceive.addListener(function (info) {
console.log('onListener registered');
if (info.socketId != socketid)
return;
else {
try {
data = ab2str(info.data);
console.log(data);
}
catch (e) {
console.log(e);
}
}
// info.data is an arrayBuffer.
});
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
回答by Ian Clelland
You're probably seeing this problem because your app has received an odd number of bytes on the socket, but you're trying to create an array of 2-byte-wide items out of it (because that's what fits into a Uint16Array
)
您可能会看到这个问题,因为您的应用程序在套接字上收到了奇数个字节,但您正在尝试从中创建一个 2 字节宽的项目数组(因为这适合Uint16Array
)
If your app receives the string "Hello"
over the network (5 bytes), then you can cast that to a Uint8Array
, and it will look like this:
如果您的应用程序"Hello"
通过网络接收字符串(5 个字节),那么您可以将其转换为 a Uint8Array
,它看起来像这样:
Item: 0 1 2 3 4
Char: H e l l o
Uint8 Value: 72 101 108 108 111
casting it to an Uint16Array
, though will try to do this:
将其强制转换为Uint16Array
,但会尝试这样做:
Item 0 1 2
Chars He ll o?
IntVal 25928 27756 ?????
Without a 6th byte to work with, it can't construct the array, and so you get an exception.
如果没有第 6 个字节可以使用,它就无法构造数组,因此会出现异常。
Using a Uint16Array
for the data only makes sense if you are expecting UCS-2 string data on the socket. If you are receiving plain ASCII data, then you want to cast that to a Uint8Array
instead, and map String.fromCharCode
on that. If it's something else, such as UTF-8, then you'll have to do some other conversion.
Uint16Array
仅当您期望套接字上有 UCS-2 字符串数据时,才对数据使用 a才有意义。如果您正在接收纯 ASCII 数据,那么您希望将其转换为 a Uint8Array
,并String.fromCharCode
在其上进行映射。如果是其他内容,例如 UTF-8,则您必须进行其他一些转换。
No matter what, though, the socket layer is always free to send you data in chunks of any length. Your app will have to deal with odd sizes, and save any remainder that you can't deal with right away, so that you can use it when you receive the next chunk of data.
不管怎样,套接字层总是可以自由地以任意长度的块向您发送数据。您的应用程序将不得不处理奇数大小,并保存您无法立即处理的任何剩余部分,以便您在收到下一个数据块时可以使用它。
回答by Xan
The modern (Chrome 38+) way to do this would be, assuming the encoding is UTF-8:
假设编码是 UTF-8,现代(Chrome 38+)方法是:
var decoder = new TextDecoder("utf-8");
function ab2str(buf) {
return decoder.decode(new Uint8Array(buf));
}
This uses the TextDecoder
API; see documentationfor more options, such as a different encoding.
这使用了TextDecoder
API;有关更多选项,例如不同的编码,请参阅文档。
See also: Easier ArrayBuffer<->String conversion with the Encoding API @ Google Developers
另请参阅:使用 Encoding API @ Google Developers 进行更简单的 ArrayBuffer<->String 转换
回答by CesarD
Kind of old and late, but perhaps using this function (original source) works better (it worked for me for decoding arraybuffer to string without leaving some special chars as total garbage):
有点旧和晚,但也许使用这个函数(原始源)效果更好(它对我有用,可以将 arraybuffer 解码为字符串,而不会留下一些特殊字符作为总垃圾):
function decodeUtf8(arrayBuffer) {
var result = "";
var i = 0;
var c = 0;
var c1 = 0;
var c2 = 0;
var data = new Uint8Array(arrayBuffer);
// If we have a BOM skip it
if (data.length >= 3 && data[0] === 0xef && data[1] === 0xbb && data[2] === 0xbf) {
i = 3;
}
while (i < data.length) {
c = data[i];
if (c < 128) {
result += String.fromCharCode(c);
i++;
} else if (c > 191 && c < 224) {
if( i+1 >= data.length ) {
throw "UTF-8 Decode failed. Two byte character was truncated.";
}
c2 = data[i+1];
result += String.fromCharCode( ((c&31)<<6) | (c2&63) );
i += 2;
} else {
if (i+2 >= data.length) {
throw "UTF-8 Decode failed. Multi byte character was truncated.";
}
c2 = data[i+1];
c3 = data[i+2];
result += String.fromCharCode( ((c&15)<<12) | ((c2&63)<<6) | (c3&63) );
i += 3;
}
}
return result;
}
回答by cuixiping
There is an asynchronousway using Blob
and FileReader
.
有一种异步方式使用Blob
and FileReader
。
You can specify any valid encoding.
您可以指定任何有效的编码。
function arrayBufferToString( buffer, encoding, callback ) {
var blob = new Blob([buffer],{type:'text/plain'});
var reader = new FileReader();
reader.onload = function(evt){callback(evt.target.result);};
reader.readAsText(blob, encoding);
}
//example:
var buf = new Uint8Array([65,66,67]);
arrayBufferToString(buf, 'UTF-8', console.log.bind(console)); //"ABC"