如何实现hex2bin()函数?

27
我需要在JavaScript和PHP之间进行通信(我使用jQuery进行AJAX),但是PHP脚本的输出可能包含二进制数据。因此,我在PHP端使用了bin2hex()和json_encode()。
如何使用JavaScript将十六进制字符串转换为二进制字符串?

2
@MartyIX:这里有一个BSD许可的Javascript函数,可以实现你想要的功能。 - Andres Riofrio
10个回答

61

回答你的问题:

function Hex2Bin(n){if(!checkHex(n))return 0;return parseInt(n,16).toString(2)}

以下是一些进一步的函数,你可能会发现它们在处理二进制数据时很有用:

//Useful Functions
function checkBin(n){return/^[01]{1,64}$/.test(n)}
function checkDec(n){return/^[0-9]{1,64}$/.test(n)}
function checkHex(n){return/^[0-9A-Fa-f]{1,64}$/.test(n)}
function pad(s,z){s=""+s;return s.length<z?pad("0"+s,z):s}
function unpad(s){s=""+s;return s.replace(/^0+/,'')}

//Decimal operations
function Dec2Bin(n){if(!checkDec(n)||n<0)return 0;return n.toString(2)}
function Dec2Hex(n){if(!checkDec(n)||n<0)return 0;return n.toString(16)}

//Binary Operations
function Bin2Dec(n){if(!checkBin(n))return 0;return parseInt(n,2).toString(10)}
function Bin2Hex(n){if(!checkBin(n))return 0;return parseInt(n,2).toString(16)}

//Hexadecimal Operations
function Hex2Bin(n){if(!checkHex(n))return 0;return parseInt(n,16).toString(2)}
function Hex2Dec(n){if(!checkHex(n))return 0;return parseInt(n,16).toString(10)}

2
这似乎不能处理实际的二进制数据,而是使用二进制数据的ASCII表示。 - Michael
3
你的函数有问题,至少是Hex2BinBin2Hex。在这两个函数得到错误结果后,我甚至没有尝试其他函数。你可以自己试试Hex2Bin => Bin2Hex - Green
1
我已经使用这个集合很长时间了。现在我开始使用Hex2Bin并意识到它是错误的。我认为Bin2Hex也是错误的。 - huggie
对于这两个函数,这里有一个可用的:https://dev59.com/MXPYa4cB1Zd3GeqPj4Zk - huggie
这要看你是指1位二进制表示(0/1)还是8位二进制表示(数据字节)。在这个答案中,“bin”表示基数2(二进制1和0)。 - Phil
你的 Hex2Bin 函数只能处理单个十六进制值对以上的数据。 - Steve Owens

18

JavaScript不支持二进制数据。但是,您可以使用普通字符串来模拟。

var hex = "375771", // ASCII HEX: 37="7", 57="W", 71="q"
    bytes = [],
    str;

for(var i=0; i< hex.length-1; i+=2){
    bytes.push(parseInt(hex.substr(i, 2), 16));
}

str = String.fromCharCode.apply(String, bytes);

alert(str); // 7Wq

当这个答案被写下时,它可能是正确的,但是现在JS支持二进制数据了,使用Uint8Array :) 相比于PHP的二进制字符串,它非常麻烦,因为本质上它们已经是Uint8Array了,但总比没有好 ¯\(ツ)/¯。 - hanshenrik

10
function hex2bin(hex)
{
    var bytes = [], str;

    for(var i=0; i< hex.length-1; i+=2)
        bytes.push(parseInt(hex.substr(i, 2), 16));

    return String.fromCharCode.apply(String, bytes);    
}

感谢Andris的帮助!


关于这个主题(dex2bin、bin2dec),可以在这里找到其他有用的信息。 根据那里的内容,这是一个bin2hex解决方案:

parseInt(1100,2).toString(16); //--> c

5

虽然这并不是对实际问题的答案,但在这种情况下也知道如何反向执行该过程可能很有用:

function bin2hex (bin)
{

  var i = 0, l = bin.length, chr, hex = ''

  for (i; i < l; ++i)
  {

    chr = bin.charCodeAt(i).toString(16)

    hex += chr.length < 2 ? '0' + chr : chr

  }

  return hex

}

作为例子,对于b637eb9146e84cb79f6d981ac9463de1使用hex2bin函数会返回¶7ëFèL·mÉF=á,然后将其传递给bin2hex函数将返回b637eb9146e84cb79f6d981ac9463de1
将这些函数原型化到String对象中可能也会很有用:
String.prototype.hex2bin = function ()
{

  var i = 0, l = this.length - 1, bytes = []

  for (i; i < l; i += 2)
  {
    bytes.push(parseInt(this.substr(i, 2), 16))
  }

  return String.fromCharCode.apply(String, bytes)   

}

String.prototype.bin2hex = function ()
{

  var i = 0, l = this.length, chr, hex = ''

  for (i; i < l; ++i)
  {

    chr = this.charCodeAt(i).toString(16)

    hex += chr.length < 2 ? '0' + chr : chr

  }

  return hex

}

alert('b637eb9146e84cb79f6d981ac9463de1'.hex2bin().bin2hex())

如果我想将一个大的图像文件转换成十六进制字符串,bin2hex似乎非常低效(而且慢)... - Michael

3

关于node.js(不在浏览器中)。

基本上过度设计了,而且工作效果不佳。

响应不对齐,尽管从文本方面来说它们是相同的,但比特位却到处都是。

curl http://phpimpl.domain.com/testhex.php | xxd

00000000: de56 a735 4739 c01d f2dc e14b ba30 8af0  .Q.%G9.....;.0..

curl http://nodejs.domain.com/ | xxd

00000000: c39e 56c2 a725 4739 c380 c3ad c3b1 c39c  ..Q..%G9........
00000010: c3a1 37c2 6b30 c28f c3b0                 ..;..0....

在Node中正确的实现方式是:
function hex2bin(hex){
   return new Buffer(hex,"hex");
}


curl http://nodejs.domain.com/ | xxd

00000000: de56 a735 4739 c01d f2dc e14b ba30 8af0  .Q.%G9.....;.0..

希望这能帮到您。

3
所有提出的解决方案都使用 String.fromCharCode,为什么不直接使用 unescape
String.prototype.hex2bin = function()
{ 
   var i = 0, len = this.length, result = "";

   //Converting the hex string into an escaped string, so if the hex string is "a2b320", it will become "%a2%b3%20"
   for(; i < len; i+=2)
      result += '%' + this.substr(i, 2);      

   return unescape(result);
}

然后:

alert( "68656c6c6f".hex2bin() ); //shows "hello"

为什么不直接使用unescape - 只是因为它已经过时了。 ;) - yckart
你可以使用decodeURIComponent代替unescape,这样做完全没有问题。感谢@Marco,我使用了你的解决方案。 - Alan Mroczek

1
这是一个使用JS实现的hex2bin函数,它接受一个字符串并返回Uint8Array,在浏览器和nodejs中都可以使用。
function hex2bin(hex) {
  var length = hex.length / 2;
  var result = new Uint8Array(length);
  for (var i = 0; i < length; ++i) {
    result[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
  }
  return result;
}

以及它的逆运算,

function bin2hex(bin) {
  return Array.from(bin).map(function (x) {
    return x.toString(16).padStart(2, '0');
  }).join('');
}

0

String.prototype.hex2bin = function () {
    if (this.length % 2 !== 0) return false;

    let bytes = []
    for (let i = 0; i < this.length - 1; i += 2) {
        let charCode = parseInt(this.substring(i, i + 2), 16)
        bytes.push(charCode)
    }

    return String.fromCharCode.apply(String, bytes)
        .replace(/\x00+$/g, '') // not necessary
        .trim()
}
    
console.log('78534F4C41527800000000000000000000000000'.hex2bin()) // xSOLARx (length: 7)
console.log('4D554C5449504153530000000000000000000000'.hex2bin()) // MULTIPASS (length: 9)
console.log('4C5A415200000000000000000000000000000000'.hex2bin()) // LZAR (length: 4)


1
目前来看,你的回答不够清晰。请编辑以添加更多细节,帮助其他人理解这如何回答所提出的问题。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - Community

-1
如果有人需要另一个方向的转换(二进制到十六进制),这里是代码:
function bin2hex(bin) {
    return new Buffer(bin).toString("hex");
}

1
未捕获的引用错误:未定义缓冲区。 - Phil

-1

JavaScript实际上包含对二进制数据的支持。请参见Uint8Array

只需从数组中读取每个字节并将其转换为十六进制即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接