1

我有 200k 行和 3 种 MAC 地址的 csv 文件,定义为:

  • ECE1A9312000
  • E8:6D:52:75:2D:16
  • 24-C9-A1-15-89-B0

我的目标是只使用冒号分隔的形式。

所以转换-:没什么大不了的:

mac = mac.replace("-", ":");

但是如何转换ECE1A9312000EC:E1:A9:31:20:00.

我想使用正则表达式,但是对于这么多数据(~80k)使用组太昂贵了。

我是否需要遍历每个char并附加:

喜欢:

for(int i=0; i<mac.length(); i++){
    ch = mac.charAt(i);

    if(i % 2 == 0 && i != 0){
        tmp += ':';
    }
    tmp += ch;
}

还是有更有效的方法?

谢谢,

4

5 回答 5

3

我根据您丢弃的正则表达式方法拼凑了一个完全未优化的程序并对其进行计时。它在 650 毫秒内完成(预热时为 250 毫秒)。最慢的部分不涉及正则表达式,而是String.format. 如果我们用直接的StringBuilder方法代替它,时间会下降到 40 毫秒。

public class Test {
  static Pattern regex = Pattern.compile("(..)(..)(..)(..)(..)(..)");
  public static void main(String[] args) {
    final List<String> inMacs = new ArrayList<>(), outMacs = new ArrayList<>();
    for (int i = 0; i < 80_000; i++) inMacs.add(mac());
    final long start = System.nanoTime();
    for (String mac : inMacs) {
      final Matcher m = regex.matcher(mac);
      m.matches();
      outMacs.add(String.format("%s:%s:%s:%s:%s:%s",
          m.group(1), m.group(2), m.group(3), m.group(4), m.group(5), m.group(6)));
    }
    System.out.println("Took " + (System.nanoTime() - start)/1_000_000 + " milliseconds");
    final Iterator<String> it = outMacs.iterator();
    for (int i = 0; i < 100; i++) System.out.println(it.next());
  }

  static Random rnd = new Random();
  static String mac() {
    final long mac = (long) (rnd.nextDouble()*(1L<<48));
    return String.format("%012x", mac).toUpperCase();
  }
}

如果您真的在寻找快速解决方案,请避免使用正则表达式并使用简单的测试来检测您的 MAC 格式:

  static List<String> fixMacs(List<String> inMacs) {
    final List<String> outMacs = new ArrayList<>(inMacs.size());
    for (String mac : inMacs) outMacs.add(
          mac.charAt(2) == '-'? mac.replace("-", ":")
        : mac.charAt(2) != ':'? fixMac(mac)
        : mac);
    return outMacs;
  }

  static String fixMac(String inMac) {
    final StringBuilder b = new StringBuilder(18);
    for (int i = 0; i < inMac.length(); i++) {
      b.append(inMac.charAt(i));
      if (i%2 == 1 && i != inMac.length()-1) b.append(':');
    }
    return b.toString();
  }

使用这种方法,我为您的 80,000 个 MAC 测量了 8 毫秒。

于 2013-11-22T11:22:45.433 回答
1

尝试这个

String x="ECE1A9312000";
String finals="";
for(int i=0;i<x.length();i=i+2)
{
    if((i+2)<x.length())
finals+=x.substring(i, i+2)+":";
    if((i+2)==x.length())
    {
        finals+=x.substring(i, i+2);

    }

}
System.out.println(finals);

输出 EC:E1:A9:31:20:00

于 2013-11-22T11:05:53.670 回答
1

逐个字符地遍历它,如果找到的字符是“-”,则每两步将其替换为“:”,如果是字母或数字,则插入一个“:”字符。

于 2013-11-22T10:55:38.173 回答
1

使用正则表达式拆分每 2 个字符并使用分隔符加入String.join

public static String convertToColonSeparatedMac(String mac) {

    if (mac.contains(":"))
        return mac;

    if (mac.contains("-")) 
        return mac.replaceAll("-", ":");

    return String.join(":", mac.split("(?<=\\G.{2})"));
}

您可以在转换之前对其进行验证:

private static final Pattern MAC_PATTERN = Pattern.compile("(^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$)|([0-9A-Fa-f]{12})");

public static boolean isValidMac(String mac) {
    return MAC_PATTERN.matcher(mac).matches();
}
于 2018-02-23T12:58:42.617 回答
0
    String mac[] = {"ECE1A9312000", "24-C9-A1-15-89-B0", "E8:6D:52:75:2D:16"};

    for (int i = 0; i< mac.length; i++)
    {
        if (mac[i].charAt(2) == '-')
            mac[i] = mac[i].replace("-", ":");
        else if (mac[i].charAt(2) != ':')
            mac[i] = new StringBuilder(mac[i].substring(0,2)).append(":").append(mac[i].substring(2,4))
                    .append(":").append(mac[i].substring(4,6)).append(":").append(mac[i].substring(6,8))
                    .append(":").append(mac[i].substring(8,10)).append(":").append(mac[i].substring(10)).toString();        
    }
    for (int i = 0; i< mac.length; i++)
        System.out.println(mac[i]);

输出:

EC:E1:A9:31:20:00
24:C9:A1:15:89:B0
E8:6D:52:75:2D:16
于 2013-11-22T11:31:00.867 回答