在Javascript中将整数形式的MAC地址转换为字符串

9

我有一个以48位数字的原始MAC地址,我想将其拆分并以标准十六进制格式xx:xx:xx:xx:xx:xx进行打印。例如,原始数字81952921372024应变为78:45:c4:26:89:4a。我第一次尝试的代码是:

var suspect = {mac: 2333752735057272};
console.log(
    Number(suspect.mac & 0xFF).toString(16) + ":" +
    Number((suspect.mac & 0xFF00) >> 8).toString(16) + ":" +
    Number((suspect.mac & 0xFF0000) >> 16).toString(16) + ":" +
    Number((suspect.mac & 0xFF000000) >> 24).toString(16) + ":" +
    Number((suspect.mac & 0xFF00000000) >> 32).toString(16) + ":" +
    Number((suspect.mac & 0xFF0000000000) >> 48).toString(16));

但是因为JavaScript在进行移位操作时显然不能处理大于32位的整数,所以最后两个八位始终为0。

78:45:c4:26:0:0 

2
在Chrome中,2333752735057272..toString(16)会给我返回84a8926c44578。如果你把它的第一个数字裁掉并且反转八位字节序列,会得到什么呢? - bfavaretto
2
事实上,JavaScript 没有 >32 位整数的概念,甚至没有真正的 32 位整数;它只有一个“number”类型,表示双精度(64 位)浮点值,并且各种整数操作(如位移)会进行隐式转换为和从 32 位整数。 - ruakh
是的,之前有一个错误,数字不太对。很抱歉,应该是81952921372024。正在编辑中。 - PherricOxide
字节顺序是因为它在网络字节顺序(大端)中。我得到的数字无法真正更改,必须在转换后将所有内容翻转。 - PherricOxide
所以,只需对原始数字执行.toString(16)并按照我最初建议的方式反转八位字节即可。正如@ruakh指出的那样,由于位移操作,您正在丢失信息。 - bfavaretto
显示剩余2条评论
3个回答

20

一个简单的方法如下所示:

var mac = 81952921372024;

mac.toString( 16 )             // "4a8926c44578"
        .match( /.{1,2}/g )    // ["4a", "89", "26", "c4", "45", "78"]
        .reverse()             // ["78", "45", "c4", "26", "89", "4a"]
        .join( ':' )           // "78:45:c4:26:89:4a"

> "78:45:c4:26:89:4a"

不过我建议在整数非常短的情况下(即mac = 150),添加额外的00组以防万一:

var mac = 81952921372024;

new Array( 6 ).join( '00' )    // '000000000000'
    .match( /../g )            // [ '00', '00', '00', '00', '00', '00' ]
    .concat( 
        mac.toString( 16 )     // "4a8926c44578"
           .match( /.{1,2}/g ) // ["4a", "89", "26", "c4", "45", "78"]
    )                          // ["00", "00", "00", "00", "00", "00", "4a", "89", "26", "c4", "45", "78"]
    .reverse()                 // ["78", "45", "c4", "26", "89", "4a", "00", "00", "00", "00", "00", "00", ]
    .slice( 0, 6 )             // ["78", "45", "c4", "26", "89", "4a" ]
    .join( ':' )               // "78:45:c4:26:89:4a"

> "78:45:c4:26:89:4a"

为什么要创建一个填充了 0 的数组?直接使用由字符串化版本的 mac (mac.toString(16).match(/../g).reverse().join(':')) 产生的数组不是更容易吗,而不是将其连接到较长的数组上并进行子字符串操作? - ajp15243
@ajp15243 已更新答案并附上解释。 - oleq
不幸的是,这对我没有起作用。Mac 1025(00:00:00:00:04:01)被转换为1:40:00:00:00:00,显然是不正确的。 - Dominik
1
由于某些原因,当我在Chrome控制台中尝试上述代码时,输出的字符串总是反转的。例如,var mac = "159534546944"(根据此在线转换器是00:25:25:00:00:00)。当我运行它通过上述代码时,我得到了"00:00:00:25:25:00"。我需要始终使用.split(":").reverse().join(":")来获取正确的值。 - blueren
这可能与此无关,但在Scala中可以通过(Array.fill(6)("00") ++ new RichLong(macAddr).toHexString.split("(?<=\\G.{2})")).reverse.slice(0, 6).mkString(":")实现相同的效果。 - forevergenin

1
以下内容可以完成任务:
var hexValue = parseInt('44873434449413').toString(16);

var macaddress = [];

for (var i=0; i < hexValue.length; i=i+2) {
    macaddress.push(hexValue.substr(i,2));    
}


console.log(macaddress.join(':'));

输出:
28:cf:e9:1e:c6:05

编辑:

处理末尾的0

str='3';
if (str.length < 12) { str = pad_after(str, 12, 0);}

var hexValue = parseInt(str).toString(16);

if (hexValue.length < 12) { hexValue = pad_before(hexValue, 12, 0);}

var macaddress = [];

for (var i=0; i < hexValue.length; i=i+2) {
    macaddress.push(hexValue.substr(i,2));    
}

console.log(macaddress.join(':'));


function pad_before(n, width, z) {
  z = z || '0';
  n = n + '';
  return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}

function pad_after(n, width, z) {
  z = z || '0';
  n = n + '';
  return n.length >= width ? n : n + new Array(width - n.length + 1).join(z);
}

输出:
00:45:d9:64:b8:00


如果八位字节的两端都是零,则无法工作。例如,当hexValue = 3时,它永远不会循环并填充macaddress数组。 - PherricOxide

1

接受的答案未通过我的单元测试(将MAC地址转换为数字,然后再转换回来,期望结果等于输入)。

正如@blueren所说,接受的答案返回了一个反向的结果。

我的版本是:

(mac_num).toString(16).padStart(12, '0').match(/../g)
                .reverse()
                .slice(0, 6)
                .reverse()
                .join(':')

我的测试:

        expect(mac.toString(mac.toLong('b4:ae:2b:db:1c:3d'))).to.deep.equal('b4:ae:2b:db:1c:3d');
        expect(mac.toString(mac.toLong('00:00:00:db:1c:3d'))).to.deep.equal('00:00:00:db:1c:3d');
        expect(mac.toString(mac.toLong('b4:ae:2b:00:00:00'))).to.deep.equal('b4:ae:2b:00:00:00');
        expect(mac.toString(mac.toLong('00:00:00:00:00:00'))).to.deep.equal('00:00:00:00:00:00');
        expect(mac.toString(mac.toLong('10:00:00:00:00:00'))).to.deep.equal('10:00:00:00:00:00');
        expect(mac.toString(mac.toLong('00:00:01:00:00:00'))).to.deep.equal('00:00:01:00:00:00');
        expect(mac.toString(mac.toLong('00:00:00:00:00:01'))).to.deep.equal('00:00:00:00:00:01');

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