风流的人字拖 · 2005年度搜索风云榜· 2 月前 · |
小胡子的熊猫 · 死神摸了摸我的头盔丨也门撤侨,展现《红海行动 ...· 2 月前 · |
活泼的登山鞋 · 光孝寺(福建省建瓯市光孝寺)_百度百科· 3 月前 · |
卖萌的口罩 · 重庆市卫生健康委员会· 3 月前 · |
英姿勃勃的地瓜 · 中国摔跤队公示奥运参赛名单_国家体育总局· 4 月前 · |
我有一个Javascript ArrayBuffer,我希望被转换成一个十六进制字符串。
有人知道我可以调用的函数还是已经存在的预先编写的函数?
我只能找到数组缓冲区到字符串函数,但我希望数组缓冲区的十六进制代替。
发布于 2016-10-13 22:20:28
function buf2hex(buffer) { // buffer is an ArrayBuffer
return [...new Uint8Array(buffer)]
.map(x => x.toString(16).padStart(2, '0'))
.join('');
// EXAMPLE:
const buffer = new Uint8Array([ 4, 8, 12, 16 ]).buffer;
console.log(buf2hex(buffer)); // = 04080c10
此功能分四个步骤工作:
x
数组,它将该元素转换为十六进制字符串(例如,
12
变为
c
)。
c
变为
0c
)放在一起。
下面是另一个比较容易理解的更长的实现,但本质上也是这样:
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
发布于 2018-06-08 19:23:16
下面是一个甜蜜的ES6解决方案,它使用
padStart
,避免了基于原型调用的可接受答案的解决方案。它实际上也更快。
function bufferToHex (buffer) {
return [...new Uint8Array (buffer)]
.map (b => b.toString (16).padStart (2, "0"))
.join ("");
}
这是如何运作的:
Array
是从保存缓冲区数据的
Uint8Array
创建的。这样我们就可以修改数组以保存以后的字符串值。
Array
项都映射到它们的十六进制代码,并填充
0
字符。
发布于 2019-03-16 18:51:20
以下是按速度顺序将
ArrayBuffer
编码为十六进制的几种方法。所有的方法最初都是在火狐上测试的,但后来我在Chrome (V8)中进行了测试。在Chrome中,方法基本上是相同的,但它确实有一些细微的差别--重要的是#1是所有环境中速度最快的方法,有很大的差距。
如果要查看当前选择的 回答 有多慢,可以继续滚动到此列表的底部。
TL;DR
方法1(就在下面)是我测试的最快的编码方法。如果出于某些很好的原因,您需要支持IE,那么在预计算十六进制时,可能需要用方法6中使用的
.padStart
调用替换
.slice
调用,以确保每个八进制都是2个字符。
1.预先计算的十六进制w/
for
环(最快/基线)
这种方法计算无符号字节:
[0, 255]
的每个可能值的两个字符十六进制八进制,然后通过八进制字符串数组映射
ArrayBuffer
中的每个值。对于使用此方法的原始
回答
,应归功于Aaron。
注意: 如Cref所述 ,您可能会在V8中获得性能提升(Chrome/Chrome/Edge/Brave/等等)。通过使用循环将十六进制连接到一个大字符串中,然后在循环后返回字符串。V8似乎很好地优化了字符串连接,而火狐的性能更好,它构建了一个数组,然后
.join
在最后将其转化为字符串,就像我在下面的代码中所做的那样。这可能是一个微优化的主题,但随着优化JS编译器的一时兴起而改变。
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("");
}
2.预先计算的十六进制w/
Array.map
(~30%慢)
与上面的方法一样,我们预先计算了一个数组,其中每个索引的值是索引值的十六进制字符串,但是我们使用了一个hack,其中我们用缓冲区调用
Array
prototype的
map()
方法。这是一种更实用的方法,但是如果您真的想要速度,您将始终使用
for
循环而不是ES6数组方法,因为所有现代JS引擎都会更好地优化它们。
重要: 您不能使用
new Uint8Array(arrayBuffer).map(...)
。虽然Uint8Array
实现了ArrayLike
接口,但是它的map
方法将返回另一个Uint8Array
,它不能包含字符串(在我们的例子中是十六进制),因此是Array
原型黑客。
function hex(arrayBuffer)
return Array.prototype.map.call(
new Uint8Array(arrayBuffer),
n => byteToHex[n]
).join("");
}
3.预先计算的ASCII字符编码(~230%慢)
这是个令人失望的实验。我写这个函数是因为我认为它会比亚伦预先计算出来的十六进制八进制更快--小子,我错了LOL。当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);
}
4.
Array.prototype.map()
w/
padStart()
(~290% )
该方法使用
Number.toString()
方法映射一个字节数组,以获得十六进制,然后在必要时通过
String.padStart()
方法将八进制填充为"0“。
的重要性:
String.padStart()
是一个相对较新的标准,所以如果您计划支持早于2017年左右的浏览器或Internet,则不应该使用此标准或方法#5。如果你的用户还在使用IE,你应该到他们家安装Chrome/Firefox。帮我们大家个忙。*^D
function hex(arrayBuffer)
return Array.prototype.map.call(
new Uint8Array(arrayBuffer),
n => n.toString(16).padStart(2, "0")
).join("");
}
5.
Array.from().map()
w/
padStart()
(~370% )
这与#4相同,但是我们没有使用
Array
原型,而是从
Uint8Array
中创建一个实际的数字数组,并直接调用
map()
。不过,我们是按速度付钱的。
function hex(arrayBuffer)
return Array.from(new Uint8Array(arrayBuffer))
.map(n => n.toString(16).padStart(2, "0"))
.join("");
}
6.
Array.prototype.map()
w/
slice()
(~450% )
这是选择的答案,除非您是典型的web开发人员,否则不要使用这个答案,性能会让您感到不安(答案#1得到了许多浏览器的支持)。
function hex(arrayBuffer)
风流的人字拖 · 2005年度搜索风云榜 2 月前 |
活泼的登山鞋 · 光孝寺(福建省建瓯市光孝寺)_百度百科 3 月前 |
卖萌的口罩 · 重庆市卫生健康委员会 3 月前 |
英姿勃勃的地瓜 · 中国摔跤队公示奥运参赛名单_国家体育总局 4 月前 |