javascript中字节数组到十六进制字符串的转换
Byte array to Hex string conversion in javascript
我有一个[4,-101,122,-41,-30,23,-28,3,..]
形式的字节数组,我想将其转换为6d69f597b217fa333246c2c8
形式我正在使用以下功能
function toHexString(bytes) {
return bytes.map(function(byte) {
return (byte & 0xFF).toString(16)
}).join('')
}
这给了我一个相同形式的字符串,但我怀疑这不是一个有效的转换,因为十六进制字符串比预期的要短一些。我认为翻译应该是"0a106dc"。请告诉我,如果我错了,或者这是正确的转换,但可能我没有使用正确的字节数组
字节阵列4,-127,45,126,58,-104,41,-27,-43,27,-35,100,-50,-77,93,-16,96,105,-101,-63,48,-105,49,-67,110,111,26,84,67,-89,-7,-50,10,-12,56,47,-49,-42,-11,-8,-96,-117,-78,97,-105,9,-62,-44,-97,-73,113,96,23,112,-14,-62,103,-104,90,-14,117,78,31,-116,-7
对应转换4812d7e3a9829e5d51bdd64ceb35df060699bc1309731bd6e6f1a5443a7f9ceaf4382fcfd6f5f8a08bb261979c2d49fb771601770f2c267985af2754e1f8cf9
十六进制转换中缺少填充。你会想要使用
function toHexString(byteArray) {
return Array.from(byteArray, function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('')
}
使得每个字节恰好转换为两个十六进制数字。您的预期输出将是04812d7e3a9829e5d51bdd64ceb35df060699bc1309731bd6e6f1a5443a7f9ce0af4382fcfd6f5f8a08bb2619709c2d49fb771601770f2c267985af2754e1f8cf9
如果输入的类型类似于Uint8Array
,则使用map()
将不起作用:map()
的结果也是Uint8Array
,无法保存字符串转换的结果。
function toHexString(byteArray) {
var s = '0x';
byteArray.forEach(function(byte) {
s += ('0' + (byte & 0xFF).toString(16)).slice(-2);
});
return s;
}
更简洁、更具性能(请参阅https://jsperf.com/byte-array-to-hex-string)使用Array.reduce()的替代方案:
function toHexString(byteArray) {
return byteArray.reduce((output, elem) =>
(output + ('0' + elem.toString(16)).slice(-2)),
'');
}
(也没有"&0xFF",因为在我看来,如果传入的数组包含大于255的值,则输出应该混乱,这样用户就可以更容易地看到他们的输入是错误的。)
由于这是谷歌第一次点击"js-byte-to-hex",我需要一些时间来理解Bergi的函数,我重写了函数并添加了一些注释,使我更容易理解:
function byteToHex(byte) {
// convert the possibly signed byte (-128 to 127) to an unsigned byte (0 to 255).
// if you know, that you only deal with unsigned bytes (Uint8Array), you can omit this line
const unsignedByte = byte & 0xff;
// If the number can be represented with only 4 bits (0-15),
// the hexadecimal representation of this number is only one char (0-9, a-f).
if (unsignedByte < 16) {
return '0' + unsignedByte.toString(16);
} else {
return unsignedByte.toString(16);
}
}
// bytes is an typed array (Int8Array or Uint8Array)
function toHexString(bytes) {
// Since the .map() method is not available for typed arrays,
// we will convert the typed array to an array using Array.from().
return Array.from(bytes)
.map(byte => byteToHex(byte))
.join('');
}
- 有关
const unsignedByte = byte & 0xff
部分的更多信息,请检查"AND 0xFF做什么?" Array.from
并非在每个浏览器中都可用(例如IE11中没有),请查看如何将JavaScript类型的数组转换为JavaScript数组以了解更多信息
OP忘记为只能用4位显示的数字添加前导0
。
以前的所有解决方案都有效,但它们都需要创建许多字符串,并对创建的字符串进行串联和切片。我一直在想,既然有了类型化数组,就必须有更好的方法来实现这一点。我最初是使用node完成的,然后注释掉了使用Buffer的行,并将它们更改为TypedArrays,这样它也可以在浏览器中工作。
它有更多的代码,但速度明显更快,至少在我组装的快速jsperf(不再工作)中是这样。接受的答案中的字符串操作版本执行了37000操作/秒,而下面的代码管理了317000操作/秒。在创建字符串对象时有很多隐藏的开销。
function toHexString (byteArray) {
//const chars = new Buffer(byteArray.length * 2);
const chars = new Uint8Array(byteArray.length * 2);
const alpha = 'a'.charCodeAt(0) - 10;
const digit = '0'.charCodeAt(0);
let p = 0;
for (let i = 0; i < byteArray.length; i++) {
let nibble = byteArray[i] >>> 4;
chars[p++] = nibble > 9 ? nibble + alpha : nibble + digit;
nibble = byteArray[i] & 0xF;
chars[p++] = nibble > 9 ? nibble + alpha : nibble + digit;
}
//return chars.toString('utf8');
return String.fromCharCode.apply(null, chars);
}
IMHO,一个更简单的Typescript解决方案:
const convertHashToHex = (value: TypedArray | number[]) : string => {
return value.map(v => v.toString(16).padStart(2, '0')).join('');
}
JS版本:
const convertHashToHex = (value) => {
return value.map(v => v.toString(16).padStart(2, '0')).join('');
}
您需要用适当数量的前导零填充十六进制转换。
当将字节数组转换为十六进制数组时,我们必须考虑如何将它们作为有符号数字。如果是这样的话,我们必须先把它们转换成十进制数字。带符号数字到十进制的转换。然后,我们可以使用.toString(16)
方法将其转换为十六进制。
const hexArr = byteArr.map((byte) => {
if (byte < 0) {
byte = -((byte ^ 0xff) + 1); //converting 2s complement to a decimal number
}
//add padding at the start to ensure it's always 2 characters long otherwise '01' will be '1'
return byte.toString(16).padStart(2, '0');
});
这是ArrayBuffer:的跨浏览器解决方案
function buf2hex(buffer) {
var u = new Uint8Array(buffer),
a = new Array(u.length),
i = u.length;
while (i--) // map to hex
a[i] = (u[i] < 16 ? '0' : '') + u[i].toString(16);
u = null; // free memory
return a.join('');
};
如果在Nodejs 上运行
只需使用Buffer.toString('base64')
crypto.randomBytes(byteLength).toString('base64')
- 将十六进制字符串转换为字节数组
- JavaScript 中两个十六进制字符串的 XOR
- 在JavaScript/NodeJS中压缩十六进制字符串
- 不带编码的十六进制字符串
- 在 Javascript 中更轻松地处理十六进制字符串和十六进制值
- 从十六进制字符串中获取原始十六进制
- 实时颜色选择器 HSV 到十六进制字符串
- 如何将中文十六进制字符串解码为中文字符或JavaScript
- 在 JavaScript 中将原始图像的十六进制字符串转换为位图图像
- 用Javascript将大整数转换为十六进制字符串
- 将十六进制字符串转换为十六进制类型
- javascript中字节数组到十六进制字符串的转换
- ByteArray的十六进制字符串
- 如何从十六进制字符串构建二进制数组
- Meteor返回无效的十六进制字符串错误试图创建ObjectID
- 将十六进制字符串转换为javascript中的整数数组
- 相当于python's int('十六进制字符串',16)
- JavaScript中十六进制字符串到字节值的稳健转换
- 如何在js中将数字转换为十六进制字符串
- 如何将浮点数转换为JavaScript中的4byte十六进制字符串并返回