Javascript数组缓冲到十六进制
我有一个Javascript ArrayBuffer,我想把它转换成十六进制字符串 有人知道我可以调用的函数或已经存在的预写函数吗 我只能找到arraybuffer to string函数,但我想要数组缓冲区的hexdump。Javascript数组缓冲到十六进制,javascript,Javascript,我有一个Javascript ArrayBuffer,我想把它转换成十六进制字符串 有人知道我可以调用的函数或已经存在的预写函数吗 我只能找到arraybuffer to string函数,但我想要数组缓冲区的hexdump。 函数buf2hex(buffer){//buffer是一个ArrayBuffer return[…新Uint8Array(buffer)].map(x=>x.toString(16).padStart(2,'0')).join(“”); } //例如: const buf
函数buf2hex(buffer){//buffer是一个ArrayBuffer
return[…新Uint8Array(buffer)].map(x=>x.toString(16).padStart(2,'0')).join(“”);
}
//例如:
const buffer=新的Uint8Array([4,8,12,16]).buffer;
console.log(buf2hex(缓冲区));//=04080c10
我使用它来hexdumpArrayBuffer
s,就像节点转储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(" ")}>`;
}
功能板(n:string,width:number,z='0'){
返回n.length>=width?n:新数组(width-n.length+1);
}
函数hextump(buf:ArrayBuffer){
let view=新的UINT8阵列(buf);
让hex=Array.from(view.map)(v=>this.pad(v.toString(16),2));
返回``;
}
(使用传输的js版本):
const buffer=新的Uint8Array([4,8,12,16]).buffer;
console.log(hextump(缓冲区));//
这是一个不错的ES6解决方案,它使用了padStart
,避免了公认答案中相当混乱的基于原型调用的解决方案。它实际上也更快
工作原理:
Uint8Array
创建数组。这样我们以后就可以修改数组来保存字符串值
数组
项都映射到它们的十六进制代码,并用0
字符填充下面是另一个解决方案,在Chrome上(也可能是node上),使用
map
和toString
比其他建议快3倍:
function bufferToHex(buffer) {
var s = '', h = '0123456789ABCDEF';
(new Uint8Array(buffer)).forEach((v) => { s += h[v >> 4] + h[v & 15]; });
return s;
}
额外好处:您可以轻松选择大小写输出
请参阅此处的工作台:以下解决方案使用预计算的查找表进行正向和反向转换
// 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;
}
//查找表
变量到十六进制数组=[];
var to_byte_map={};
for(var ord=0;ord{hex_数组.push(to_hex_数组[v]));
对于(var i=0;i这里有几种将ArrayBuffer
编码为十六进制的方法,以速度为顺序。所有方法最初都在Firefox中测试过,但后来我在Chrome(V8)中测试过.在Chrome中,这些方法的顺序基本相同,但它们之间确实有一些细微的区别--重要的是#1是所有环境中速度最快的方法,相差很大
如果您想查看当前选择的速度有多慢,可以继续并滚动到此列表的底部
太长,读不下去了
方法#1(就在下面)是我测试过的最快的编码十六进制字符串的方法。如果出于某种非常好的原因,您需要支持IE,那么在预计算十六进制八位字节时,您可能需要将.padStart
调用替换为方法#6中使用的.slice
技巧,以确保每个八位字节都是2个字符
1.预计算的十六进制八位组w/用于
循环(最快/基线)
这种方法为无符号字节的每个可能值计算2个字符的十六进制八位字节:[0255]
,然后通过八位字节字符串数组映射数组缓冲区中的每个值
const byteToHex = [];
for (let n = 0; n <= 0xff; ++n)
{
const hexOctet = n.toString(16).padStart(2, "0");
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("");
}
3.预计算的ASCII字符码(大约慢230%)
这是一个令人失望的实验。我编写了这个函数,因为我认为它比Aaron预先计算的十六进制八位字节还要快——我错了吗?哈哈。Aaron将整个字节映射到对应的2字符十六进制代码,而这个解决方案使用位移位来获得每个字节前4位的十六进制字符,然后是一个是最后4个,使用了String.fromCharCode()
。老实说,我认为String.fromCharCode()
肯定没有得到很好的优化,因为它没有被很多人使用,而且在浏览器供应商的优先级列表中排名较低
const asciiCodes = new Uint8Array(
Array.prototype.map.call(
"0123456789abcdef",
char => char.charCodeAt()
)
);
function hex(arrayBuffer)
{
const buff = new Uint8Array(arrayBuffer);
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);
}
5.Array.from().map()
w/padStart()
(~370%的速度)
这与#4相同,但不是Array
prototype hack,而是从Uint8Array
创建一个实际的数字数组,并直接调用map()
。尽管如此,我们还是以速度付费
function hex(arrayBuffer)
{
return Array.from(new Uint8Array(arrayBuffer))
.map(n => n.toString(16).padStart(2, "0"))
.join("");
}
6.Array.prototype.map()
这是选定的答案,除非您是一名典型的web开发人员,而且性能让您感到不安,否则不要使用此答案(答案#1同样受到许多浏览器的支持)
第1课
对于速度权衡,预计算内容有时是非常有效的内存。理论上,预计算的十六进制八位字节数组可以存储在1024字节(256个可能的十六进制值)中⨉ 2个字符/值⨉ 大多数/所有浏览器使用的UTF-16字符串表示形式为2字节/字符),这在现代计算机中算不上什么。实际上,其中还有更多的字节用于存储数组和字符串长度以及可能的类型信息,因为这是JavaScript,但内存使用量对于大规模性能改进来说仍然可以忽略不计
第二课
帮助优化编译器。浏览器的JavaScript编译器定期尝试理解您的代码,并将其分解为最快的机器代码供CPU执行。因为JavaScript是一种非常动态的语言,这可能很难做到,有时浏览器会放弃并留下各种类型的代码由于无法确定x是否真的是字符串或数字,因此检查和更糟的是,反之亦然。使用内置数组
类的.map
方法等现代函数编程添加,可能会给浏览器带来麻烦,因为回调函数可以捕获外部变量并执行各种操作通常会影响性能的其他因素。因为循环经过了很好的研究,而且相对简单
function hex(arrayBuffer)
{
return Array.prototype.map.call(
new Uint8Array(arrayBuffer),
n => byteToHex[n]
).join("");
}
const asciiCodes = new Uint8Array(
Array.prototype.map.call(
"0123456789abcdef",
char => char.charCodeAt()
)
);
function hex(arrayBuffer)
{
const buff = new Uint8Array(arrayBuffer);
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);
}
function hex(arrayBuffer)
{
return Array.prototype.map.call(
new Uint8Array(arrayBuffer),
n => n.toString(16).padStart(2, "0")
).join("");
}
function hex(arrayBuffer)
{
return Array.from(new Uint8Array(arrayBuffer))
.map(n => n.toString(16).padStart(2, "0"))
.join("");
}
function hex(arrayBuffer)
{
return Array.prototype.map.call(
new Uint8Array(arrayBuffer),
n => ("0" + n.toString(16)).slice(-2)
).join("");
}