I\'ve got a Javascript ArrayBuffer that I would like to be converted into a hex string.
Anyone knows of a function that I can call or a pre written function already
Here is another solution which is, on Chrome (and probably node too) about 3x faster than the other suggestions using map
and toString
:
function bufferToHex(buffer) {
var s = '', h = '0123456789ABCDEF';
(new Uint8Array(buffer)).forEach((v) => { s += h[v >> 4] + h[v & 15]; });
return s;
}
Additional bonus: you can easily choose uppercase/lowercase output.
See bench here: http://jsben.ch/Vjx2V
In Node, we can use Buffer.from(unitarray, “hex”)
function buf2hex(buffer) { // buffer is an ArrayBuffer
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}
// EXAMPLE:
const buffer = new Uint8Array([ 4, 8, 12, 16 ]).buffer;
console.log(buf2hex(buffer)); // = 04080c10
This function works in four steps:
x
the array, it converts that element to a hex string (e.g., 12
becomes c
).c
becomes 0c
).Below is another longer implementation that is a little easier to understand, but essentially does the same thing:
function buf2hex(buffer) { // buffer is an ArrayBuffer
// create a byte array (Uint8Array) that we can use to read the array buffer
const byteArray = new Uint8Array(buffer);
// for each element, we want to get its two-digit hexadecimal representation
const hexParts = [];
for(let i = 0; i < byteArray.length; i++) {
// convert value to hexadecimal
const hex = byteArray[i].toString(16);
// pad with zeros to length 2
const paddedHex = ('00' + hex).slice(-2);
// push to array
hexParts.push(paddedHex);
}
// join all the hex values of the elements into a single string
return hexParts.join('');
}
// EXAMPLE:
const buffer = new Uint8Array([ 4, 8, 12, 16 ]).buffer;
console.log(buf2hex(buffer)); // = 04080c10
Here is a sweet ES6 solution, using padStart
and avoiding the quite confusing prototype-call-based solution of the accepted answer. It is actually faster as well.
function bufferToHex (buffer) {
return [...new Uint8Array (buffer)]
.map (b => b.toString (16).padStart (2, "0"))
.join ("");
}
How this works:
Array
is created from a Uint8Array
holding the buffer data. This is so we can modify the array to hold string values later.Array
items are mapped to their hex codes and padded with 0
characters.The simplest way to convert arraybuffer to hex:
const buffer = new Uint8Array([ 4, 8, 12, 16 ]);
console.log(Buffer.from(buffer).toString("hex")); // = 04080c10
The following solution uses precomputed lookup tables for both forward and backward conversion.
// look up tables
var to_hex_array = [];
var to_byte_map = {};
for (var ord=0; ord<=0xff; ord++) {
var s = ord.toString(16);
if (s.length < 2) {
s = "0" + s;
}
to_hex_array.push(s);
to_byte_map[s] = ord;
}
// converter using lookups
function bufferToHex2(buffer) {
var hex_array = [];
//(new Uint8Array(buffer)).forEach((v) => { hex_array.push(to_hex_array[v]) });
for (var i=0; i<buffer.length; i++) {
hex_array.push(to_hex_array[buffer[i]]);
}
return hex_array.join('')
}
// reverse conversion using lookups
function hexToBuffer(s) {
var length2 = s.length;
if ((length2 % 2) != 0) {
throw "hex string must have length a multiple of 2";
}
var length = length2 / 2;
var result = new Uint8Array(length);
for (var i=0; i<length; i++) {
var i2 = i * 2;
var b = s.substring(i2, i2 + 2);
result[i] = to_byte_map[b];
}
return result;
}
This solution is faster than the winner of the previous benchmark: http://jsben.ch/owCk5 tested in both Chrome and Firefox on a Mac laptop. Also see the benchmark code for a test validation function.
[edit: I change the forEach to a for loop and now it's even faster.]