how to convert arraybuffer to string
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«
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:
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'); >);
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)
4 Answers 4
The modern (Chrome 38+) way to do this would be, assuming the encoding is UTF-8:
var decoder = new TextDecoder("utf-8"); function arrayBufferToString(buffer)
This uses the TextDecoder API; see documentation for more options, such as a different encoding.
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 )
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:
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:
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.
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.
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.
Typescript arraybuffer to string
How to convert ArrayBuffer to and from String
Published on Thursday, June 14, 2012 • Updated on Saturday, February 9, 2019
Renato is a contributor to Chrome Developers
Update, August 2014: The Encoding API specification has matured, and a number of browsers now support it natively. The information in this article still applies for browsers that don’t yet support the Encoding API, but the recommended approach is to use the official API wherever possible. See Easier ArrayBuffer String conversion with the Encoding API for more details.
ArrayBuffers are used to transport raw data and several new APIs rely on them, including WebSockets, Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) and WebWorkers. However, because they recently landed in the JavaScript world, sometimes they are misinterpreted or misused.
Semantically, an ArrayBuffer is simply an array of bytes viewed through a specific mask. This mask, an instance of ArrayBufferView, defines how bytes are aligned to match the expected structure of the content. For example, if you know that the bytes in an ArrayBuffer represent an array of 16-bit unsigned integers, you just wrap the ArrayBuffer in a Uint16Array view and you can manipulate its elements using the brackets syntax as if the Uint16Array was an integer array:
// suppose buf contains the bytes [0x02, 0x01, 0x03, 0x07]
// notice the multibyte values respect the hardware endianess, which is little-endian in x86
var bufView = new Uint16Array(buf);
if (bufView[0]===258) // 258 === 0x0102
console.log("ok");
>
bufView[0] = 255; // buf now contains the bytes [0xFF, 0x00, 0x03, 0x07]
bufView[0] = 0xff05; // buf now contains the bytes [0x05, 0xFF, 0x03, 0x07]
bufView[1] = 0x0210; // buf now contains the bytes [0x05, 0xFF, 0x10, 0x02]
One common practical question about ArrayBuffer is how to convert a String to an ArrayBuffer and vice-versa. Since an ArrayBuffer is, in fact, a byte array, this conversion requires that both ends agree on how to represent the characters in the String as bytes. You probably have seen this «agreement» before: it is the String’s character encoding (and the usual «agreement terms» are, for example, Unicode UTF-16 and iso8859-1). Thus, supposing you and the other party have agreed on the UTF-16 encoding, the conversion code could be something like:
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;
>
Note the use of Uint16Array . This is an ArrayBuffer view that aligns bytes of the ArrayBuffers as 16-bit elements. It doesn’t handle the character encoding itself, which is handled as Unicode by String.fromCharCode and str.charCodeAt .
Note: A robust implementation of the String to ArrayBuffer conversion capable of handling more encodings is provided by the stringencoding library. But, for simple usage where you control both sides of the communication pipe, the code above is probably enough. A standardized API specification for String encoding is being drafted by the WHATWG working group.
A popular StackOverflow question about this has a highly voted answer with a somewhat convoluted solution to the conversion: create a FileReader to act as a converter and feed a Blob containing the String into it. Although this method works, it has poor readability and I suspect it is slow. Since unfounded suspicions have driven many mistakes in the history of humanity, let’s take a more scientific approach here. I have jsperf’ed the two methods and the result confirms my suspicion and you check out the demo here.
In Chrome 20, it is almost 27 times faster to use the direct ArrayBuffer manipulation code on this article than it is to use the FileReader / Blob method.
Updated on Saturday, February 9, 2019 • Improve article
Converting array buffer in string
I am stuck in converting arraybuffer to string in typescript (angular 4 project). Any help is highly appreciated. Code output is showing string but with this sign — � Required Output :
PROGRAM «Digitala †rsredovisningen»
PROGRAM «Digitala �rsredovisningen»
5 Answers 5
You should try something like this:
function uintToString(uintArray)
This will allow unicode characters
From this reference you can check the following:
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; >
Additionally, if you can use using TextEncoder and TextEncoder , check this answer.
I had a SHA256 hash that i needed to convert to String.
function ab2str(hashBuffer) < const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map(b =>('00' + b.toString(16)).slice(-2)).join(''); return hashHex; >
If you are having the same problem as Shifali singla (chinese characters) just change this:
return String.fromCharCode.apply(null, new Uint16Array(arraybuffer));
return String.fromCharCode.apply(null, new Uint8Array(arraybuffer));
the buffer is probably coming in a unit8array and not in a unit16array
ArrayBuffer to String, String to ArrayBuffer Method(s)
This question has received answers in the past, but I would definitely say that it is still not answered. There is almost documentation on ArrayBuffers in general, let alone on specific applications. I have been researching for days to no avail on this. Essentially I need to try to convert an ArrayBuffer that I got from a file reader (here: https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsArrayBuffer) to a string, and then convert that string back to the same ArrayBuffer. I have tried these methods for example
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; ireturn b
I get the following error: "byte length of Uint16Array should be a multiple of 2" I also tried the following
function StringToUint8Array(string) < var binary, binLen, buffer, chars, i, _i; binary = StringToBinary(string); binLen = binary.length; buffer = new ArrayBuffer(binLen); chars = new Uint8Array(buffer); for (i = _i = 0; 0 binLen; i = 0 return chars; > function ArrayBufferToString(buffer) < return BinaryToString(String.fromCharCode.apply(null, Array.prototype.slice.apply(new Uint8Array(buffer)))); >function StringToArrayBuffer(string) < return StringToUint8Array(string).buffer; >function BinaryToString(binary) < var error; try < return decodeURIComponent(escape(binary)); >catch (_error) < error = _error; if (error instanceof URIError) < return binary; >else < throw error; >> > function StringToBinary(string) < var chars, code, i, isUCS2, len, _i; len = string.length; chars = []; isUCS2 = false; for (i = _i = 0; 0 len; i = 0 255) < isUCS2 = true; chars = null; break; >else < chars.push(code); >> if (isUCS2 === true) < return unescape(encodeURIComponent(string)); >else < return String.fromCharCode.apply(null, Array.prototype.slice.apply(chars)); >>
And received this error: Maximum call stack size exceeded It seems that there are just no good methods for the following conversions: AB --> String || String -> AB