Javascript ArrayBuffer - Hex

У меня есть Javascript ArrayBuffer, который я хотел бы преобразовать в шестнадцатеричную строку.

Кто-нибудь знает о функции, которую я могу назвать, или предварительно написанной функции уже там?

Я только смог найти arraybuffer для строковых функций, но вместо этого я хочу использовать hexdump буфера массива.

Ответы

Ответ 1

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

Ответ 2

Вот приятное решение ES6, использующее padStart и позволяющее избежать довольно запутанного решения о принятом ответе на основе вызова прототипа. Это на самом деле быстрее, а также.

function bufferToHex (buffer) {
    return Array
        .from (new Uint8Array (buffer))
        .map (b => b.toString (16).padStart (2, "0"))
        .join ("");
}

Как это работает:

  1. Array создается из Uint8Array содержащего данные буфера. Это так, что мы можем изменить массив для хранения строковых значений позже.
  2. Все элементы Array сопоставляются с их шестнадцатеричными кодами и дополняются 0 символами.
  3. Массив объединяется в полную строку.

Ответ 3

Вот еще одно решение, которое в Chrome (и, вероятно, тоже в узле) примерно в 3 раза быстрее, чем другие предложения, использующие map и toString:

function bufferToHex(buffer) {
    var s = '', h = '0123456789ABCDEF';
    (new Uint8Array(buffer)).forEach((v) => { s += h[v >> 4] + h[v & 15]; });
    return s;
}

Дополнительный бонус: вы можете легко выбрать прописные/строчные буквы.

Смотрите скамейку здесь: http://jsben.ch/Vjx2V

Ответ 4

Я использую это для ArrayBuffer же, как Node ArrayBuffer 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(" ")}>';
}

= width? n: new Array(width%20- 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 ``; } const buffer = new Uint8Array([ 4, 8, 12, 16 ]).buffer; console.log(hexdump(buffer));// rel="nofollow noreferrer">Пример (с измененной версией js):

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

Ответ 5

Следующее решение использует предварительно вычисленные таблицы поиска для прямого и обратного преобразования.

// 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;
}

Это решение быстрее, чем победитель предыдущего теста: http://jsben.ch/owCk5, протестированный в Chrome и Firefox на ноутбуке Mac. Также см. Контрольный код для функции проверки теста.

[edit: я изменяю forEach на цикл for, и теперь он стал еще быстрее.]