2013-11-22 134 views
1

我有20萬行和3種類型的MAC地址的csv文件定義爲:如何MAC字符串轉換爲冒號分隔的串

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

我的目標只用冒號分隔的形式留下來。

所以轉換-:不是什麼大不了的:

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

但如何ECE1A9312000轉換爲EC: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; 
} 

或有更有效的方法?

謝謝

+0

80k是非常少的數據。你應該發佈你的正則表達式代碼和特定的時間結果。 –

回答

2

我扔在一起,根據您的正則表達式的丟棄方式完全未經優化的程序和定時它。它在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(); 
    } 

通過這種方法,我測量只有8毫秒的80000 Mac電腦。

+0

謝謝你@MarkoTopolnik,不能給予好評,只有3 PRES – snaggs

1

迭代來逐個字符,每兩個步驟,如果發現字符爲「 - 」,取而代之的是「:」,如果它是一個字母或再一個號碼中插入「:」字符。

+0

這不是我問的,我需要'ECE1A9312000 - > EC:E1:A9:31:20:00' – snaggs

+0

@fessy檢查我的答案,讓我知道,如果你想這樣或那樣不 – SpringLearner

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

+0

你認爲針對其更快的方法我張貼在上面? 'substring',嗯 – snaggs

+0

@fessy在你途中的for循環將12次運行,因爲你正在做我+ +,但我做的我= 2但這不會通過字符,而不是matter.But讀取字符的爲什麼不串它也讓我知道你是否有任何其他查詢。 – SpringLearner

+0

這是這個問題最簡單和最好的答案。 –

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]); 

OUTPUT:

EC:E1:A9:31:20:00 
24:C9:A1:15:89:B0 
E8:6D:52:75:2D:16 
+0

@MarkoTopolnik是的!謝謝!我已將其刪除。 – neutrino

+0

我已經計時了,它和我的正則表達式一樣快(或慢)。我不認爲OP對績效的抱怨是站得住腳的。 –

+0

順便說一句,因爲輸入只限於三種格式,檢測格式的最有效方法是檢查'mac [2]'。 –

0

分割,每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(); 
} 
相關問題