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 ("");
}
Как это работает:
-
Array
создается из Uint8Array
содержащего данные буфера. Это так, что мы можем изменить массив для хранения строковых значений позже. - Все элементы
Array
сопоставляются с их шестнадцатеричными кодами и дополняются 0
символами. - Массив объединяется в полную строку.
Ответ 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, и теперь он стал еще быстрее.]