# Javascript ArrayBuffer to Hex

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 out there?

I have only been able to find arraybuffer to string functions, but I want the hexdump of the array buffer instead.

``````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:

1. Converts the buffer into an array.
2. For each `x` the array, it converts that element to a hex string (e.g., `12` becomes `c`).
3. Then it takes that hex string and left pads it with zeros (e.g., `c` becomes `0c`).
4. Finally, it takes all of the hex values and joins them into a single string.

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++) {
const hex = byteArray[i].toString(16);

// pad with zeros to length 2
const paddedHex = ('00' + hex).slice(-2);

// push to array
}

// 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 Array
.from (new Uint8Array (buffer))
.map (b => b.toString (16).padStart (2, "0"))
.join ("");
}
``````

How this works:

1. An `Array` is created from a `Uint8Array` holding the buffer data. This is so we can modify the array to hold string values later.
2. All the `Array` items are mapped to their hex codes and padded with `0` characters.
3. The array is joined into a full string.

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

Here are several methods for encoding an `ArrayBuffer` to hex, in order of speed. All methods were tested in Firefox initially, but afterwards I went and tested in Chrome (V8). In Chrome the methods were mostly in the same order but it did have slight differenences--the important thing is that #1 is the fastest method in all environments by a huge margin.

If you want to see how slow the currently selected answer is, you can go ahead and scroll to the bottom of this list lmao.

## Attention Copy-Pasters

Be good boys/girls and use solution #1. It is both the fastest and the best supported. The only faster method of encoding to hex in a browser is writing optimized C code and compiling to Web Assembly.

# 1. Precomputed Hex Octets w/ `for` Loop (Fastest/Baseline)

This approach computes the 2-character hex octets for every possible value of an unsigned byte: `[0, 255]`, and then just maps each value in the `ArrayBuffer` through the array of octet strings. Credit to Aaron Watters for the original answer using this method.

``````const byteToHex = [];

for (let n = 0; n <= 0xff; ++n)
{
byteToHex.push(hexOctet);
}

function hex(arrayBuffer)
{
const buff = new Uint8Array(arrayBuffer);
const hexOctets = []; // new Array(buff.length) is even faster (preallocates necessary array size), then use hexOctets[i] instead of .push()

for (let i = 0; i < buff.length; ++i)
hexOctets.push(byteToHex[buff[i]]);

return hexOctets.join("");
}
``````

# 2. Precomputed Hex Octets w/ `Array.map` (~30% slower)

Same as the above method, where we precompute an array in which the value for each index is the hex string for the index's value, but we use a hack where we call the `Array` prototype's `map()` method with the buffer. This is a more functional approach, but if you really want speed you will always use `for` loops rather than ES6 array methods, as all modern JS engines optimize them much better.

IMPORTANT: You cannot use `new Uint8Array(arrayBuffer).map(...)`. Although `Uint8Array` implements the `ArrayLike` interface, its `map` method will return another `Uint8Array` which cannot contain strings (hex octets in our case), hence the `Array` prototype hack.

``````function hex(arrayBuffer)
{
return Array.prototype.map.call(
new Uint8Array(arrayBuffer),
n => byteToHex[n]
).join("");
}
``````

# 3. Precomputed ASCII Character Codes (~230% slower)

Well this was a disappointing experiment. I wrote up this function because I thought it would be even faster than Aaron's precomputed hex octets--boy was I wrong LOL. While Aaron maps entire bytes to their corresponding 2-character hex codes, this solution uses bitshifting to get the hex character for the first 4 bits in each byte and then the one for the last 4 and uses `String.fromCharCode()`. Honestly I think `String.fromCharCode()` must just be poorly optimized, since it is not used by very many people and is low on browser vendors' lists of priorities.

``````const asciiCodes = new Uint8Array(
Array.prototype.map.call(
"0123456789abcdef",
char => char.charCodeAt()
)
);

function hex(arrayBuffer)
{
const buff = new Uint8Array(buff);
const charCodes = new Uint8Array(buff.length * 2);

for (let i = 0; i < buff.length; ++i)
{
charCodes[i * 2] = asciiCodes[buff[i] >>> 4];
charCodes[i * 2 + 1] = asciiCodes[buff[i] & 0xf];
}

return String.fromCharCode(...charCodes);
}
``````

# 4. `Array.prototype.map()` w/ `padStart()` (~290% slower)

This method maps an array of bytes using the `Number.toString()` method to get the hex and then padding the octet with a "0" if necessary via the `String.padStart()` method.

IMPORTANT: `String.padStart()` is a relative new standard, so you should not use this or method #5 if you are planning on supporting browsers older than 2017 or so or Internet Explorer. TBH if your users are still using IE you should probably just go to their houses at this point and install Chrome/Firefox. Do us all a favor. :^D

``````function hex(arrayBuffer)
{
return Array.prototype.map.call(
new Uint8Array(arrayBuffer),
).join("");
}
``````

# 5. `Array.from().map()` w/ `padStart()` (~370% slower)

This is the same as #4 but instead of the `Array` prototype hack, we create an actual number array from the `Uint8Array` and call `map()` on that directly. We pay in speed though.

``````function hex(arrayBuffer)
{
return Array.from(new Uint8Array(arrayBuffer))
.join("");
}
``````

# 6. `Array.prototype.map()` w/ `slice()` (~450% slower)

This is the selected answer, do not use this unless you are a typical web developer and performance makes you uneasy (answer #1 is supported by just as many browsers).

``````function hex(arrayBuffer)
{
return Array.prototype.map.call(
new Uint8Array(arrayBuffer),
n => ("0" + n.toString(16)).slice(-2)
).join("");
}
``````

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.]

The simplest way to convert arraybuffer to hex:

``````const buffer = new Uint8Array([ 4, 8, 12, 16 ]);
console.log(Buffer.from(buffer).toString("hex")); // = 04080c10
``````

I use this to hexdump `ArrayBuffer`s the same way that Node dumps `Buffer`s.

``````function pad(n: string, width: number, z = '0') {
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
function hexdump(buf: ArrayBuffer) {
let view = new Uint8Array(buf);
let hex = Array.from(view).map(v => this.pad(v.toString(16), 2));
return `<Buffer \${hex.join(" ")}>`;
}
``````

Example (with transpiled js version):

``````const buffer = new Uint8Array([ 4, 8, 12, 16 ]).buffer;
console.log(hexdump(buffer)); // <Buffer 04 08 0c 10>
``````

This one's inspired by Sam Claus' #1 which is indeed the fastest method on here. Still, I've found that using plain string concatenation instead of using an array as a string buffer is even faster! At least it is on Chrome. (which is V8 which is almost every browser these days and NodeJS)

``````const len = 0x100, byteToHex = new Array(len), char = String.fromCharCode;
let n = 0;
for (; n < 0x0a; ++n) byteToHex[n] = '0' + n;
for (; n < 0x10; ++n) byteToHex[n] = '0' + char(n + 87);
for (; n < len; ++n) byteToHex[n] = n.toString(16);
function byteArrayToHex(byteArray) {
const l = byteArray.length;
let hex = '';
for (let i = 0; i < l; ++i) hex += byteToHex[byteArray[i] % len];
return hex;
}
function bufferToHex(arrayBuffer) {
return byteArrayToHex(new Uint8Array(arrayBuffer));
}
``````

In Node, we can use `Buffer.from(unitarray, “hex”)`