详解Java如何跨平台获取MAC地址

 更新时间:2021年06月01日 08:37:58   作者:庄周de蝴蝶  
有时我们因为软件授权或者其它需要获取主机唯一标识而需要获取用户主机的MAC地址,而本文则将介绍如何通过Java来实现跨平台获取MAC地址的两种方法,需要的朋友可以参考下

使用 NetworkInterface 类

首先介绍如何通过JavaNetworkInterface类的API来获取本机MAC地址的方法,首先展示代码:

/**
 * 获取 mac 地址工具类 v1 版
 *
 * @date 2021/5/13
 * @author zjw
 */
public class MacUtil {

    public static void main(String[] args) {
        getMac().forEach(System.out::println);
    }

    /**
     * 获取本机 mac 地址集合
     *
     * @return mac 地址集合
     */
    public static List<String> getMac() {
        List<String> list = new ArrayList<>();
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                Optional.ofNullable(networkInterface.getHardwareAddress())
                        .ifPresent(mac -> list.add(format(mac)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 将 mac 字节数组格式化为全大写并且使用 - 作为分隔符的字符串
     *
	 * @param mac 获取到的 mac 字节数组
     *
     * @return 格式化后的 mac 地址
     */
    private static String format(byte[] mac) {
        StringBuilder sb = new StringBuilder();
        for (byte b : mac) {
            sb.append(String.format("%02X", b)).append("-");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

}

通过以上代码理论上即可获取本机所有的MAC地址,此外通过format方法可以将获取到的MAC地址统一处理成XX-XX-XX-XX-XX-XX的格式,这里之所以说是理论上,是因为我曾经在别人的苹果电脑上运行,结果并没有得到所有MAC地址(没有得到执行ifconfig -a得到的所有MAC地址,而且还会出现llw0这个网络的MAC地址一直变动),但是我在本地的虚拟机中运行苹果时却也是正常,由于我自己没有苹果电脑,所以暂时也不清楚具体的原因,如果有知道的小伙伴,欢迎留言,提前感谢啦~~~

执行命令行获取

正如在上一部分中提到的,在某些情况下使用NetworkInterface类并不能获取到本机所有的MAC地址,甚至还可能出现动态变化的情况(暂时不清楚原因)。因此,在这种情况下只能通过JavaRuntime类的exec方法直接执行命令了,当然在大多数情况下还是建议使用NetworkInterface类,不仅方便,而且万一以后修复了上面的bug(不知道算不算是bug,还是我个人的问题),不对上述代码做任何变动就可以得到自己执行命令的效果了,说了那么多,先看看如果通过自己执行命令获取本机的所有MAC地址吧,先直接展示代码:

/**
 * 获取 mac 地址工具类 v2 版
 *
 * @date 2021/5/13
 * @author zjw
 */
public class MacUtil {

    private static final String WIN_PREFIX = "win";
    private static final String OS_NAME_PROPERTY = "os.name";
    private static final String WIN_COMMAND = "ipconfig /all";
    private static final String UNIX_COMMAND = "/sbin/ifconfig -a";
    private static final String MAC_REGEX = "(([a-f0-9]{2}-){5}|([a-f0-9]{2}:){5})[a-f0-9]{2}";
    private static final Pattern pattern = Pattern.compile(MAC_REGEX, Pattern.CASE_INSENSITIVE);

    public static void main(String[] args) {
        getMac().forEach(System.out::println);
    }

    /**
     * 根据不同操作系统执行不同命令
     * 获取本机 mac 地址集合
     *
     * @return mac 地址集合
     */
    private static List<String> getMac() {
        try {
            String osName = System.getProperty(OS_NAME_PROPERTY).toLowerCase();
            if (osName.startsWith(WIN_PREFIX)) {
                return getMacByCommand(WIN_COMMAND);
            }
            return getMacByCommand(UNIX_COMMAND);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Collections.emptyList();
    }

    /**
     * 通过正则表达式提取执行命令得到的结果集中的 mac 地址
     * 并调整得到的 mac 地址的格式
     *
	 * @param command 查看网络信息的命令
     *
     * @return mac 地址集合
     */
    private static List<String> getMacByCommand(String command) throws IOException {
        List<String> macList = new ArrayList<>();
        List<String> strList = execCommand(command);
        for (String str : strList) {
            Matcher matcher = pattern.matcher(str);
            if (matcher.find() && matcher.end() == str.length()) {
                macList.add(matcher.group().replace(":", "-").toUpperCase());
            }
        }
        return macList;
    }

    /**
     * 执行命令并得到结果的每一行组成的字符串数组
     *
	 * @param command 查看网络信息的命令
     *
     * @return 执行命令返回的所有数据行
     */
    private static List<String> execCommand(String command) throws IOException {
        List<String> strList = new ArrayList<>();
        Process process = Runtime.getRuntime().exec(command);
        try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            return br.lines().collect(Collectors.toList());
        } catch (Exception e) {
            e.printStackTrace();
        }
        process.destroy();
        return strList;
    }

}

源码

到此这篇关于详解Java如何跨平台获取MAC地址的文章就介绍到这了,更多相关Java跨平台获取MAC地址内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java 将文件转为字节数组知识总结及实例详解

    Java 将文件转为字节数组知识总结及实例详解

    这篇文章主要介绍了Java 将文件转为字节数组实例详解的相关资料,需要的朋友可以参考下
    2016-12-12
  • 图书管理系统java版

    图书管理系统java版

    这篇文章主要为大家详细介绍了java版的图书管理系统,通过实例为大家快速掌握数据库编程技术,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • 使用MyBatis查询千万级数据量操作实现

    使用MyBatis查询千万级数据量操作实现

    这篇文章主要为大家介绍了如何使用MyBatis 查询千万数据量的操作过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • 深入了解Java核心类库--Objects类

    深入了解Java核心类库--Objects类

    这篇文章主要介绍了Java中的Object类详细介绍,本文讲解了Object类的作用、Object类的主要方法、Object类中不能被重写的方法、Object类的equals方法重写实例等内容,需要的朋友可以参考下
    2021-07-07
  • Spring Boot Security配置教程

    Spring Boot Security配置教程

    在本文里我们给大家分享了关于Spring Boot Security配置的相关步骤以及注意要点,需要的朋友们跟着操作下。
    2019-05-05
  • Java数据结构之链表的增删查改详解

    Java数据结构之链表的增删查改详解

    今天带大家来学习Java链表的增删改查的相关知识,文中有非常详细的代码示例,对正在学习Java的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-05-05
  • java微信开发第二步 获取消息和回复消息

    java微信开发第二步 获取消息和回复消息

    这篇文章主要为大家分享java微信开发的第二步,如何获取消息和回复消息,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • Java使用poi-tl1.9.1生成Word文档的技巧分享

    Java使用poi-tl1.9.1生成Word文档的技巧分享

    本文将简单介绍poi-tl的相关知识,通过一个实际的案例实践,充分介绍如何利用poi-tl进行目标文档的生成,同时分享几个不同的office版本如何进行图表生成的解决方案,需要的朋友可以参考下
    2023-09-09
  • Java的线程池ThreadPoolExecutor及多种线程池实现详解

    Java的线程池ThreadPoolExecutor及多种线程池实现详解

    这篇文章主要介绍了Java的线程池ThreadPoolExecutor及多种线程池实现详解,ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量,之所以将信息存储在一个变量中,是为了保证原子性,需要的朋友可以参考下
    2024-01-01
  • MybatisPlus操作符和运算值详解

    MybatisPlus操作符和运算值详解

    在前端到后端的数据传递中,处理动态运算条件是一个常见的需求,本文介绍了如何在MybatisPlus中处理运算符和运算值的动态拼接问题,感兴趣的朋友一起看看吧
    2024-10-10

最新评论