2014-12-05 2 views
0

Я читаю logfile в java. Для каждой строки в файле журнала я проверяю, содержит ли строка ip-адрес. Если строка содержит IP-адрес, я хочу, чтобы затем +1 к числу количества раз, которое ip-адрес появился в файле журнала. Как я могу выполнить это на Java?подсчет уникальных вхождений строки в документе

Код ниже успешно извлекает ip-адрес из каждой строки, содержащей IP-адрес, но процесс подсчета входов ip-адресов не работает.

void read(String fileName) throws IOException { 
    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName))); 
    int counter = 0; 
    ArrayList<IPHolder> ips = new ArrayList<IPHolder>(); 
    try { 
     String line; 
     while ((line = br.readLine()) != null) { 
      if(!getIP(line).equals("0.0.0.0")){ 
       if(ips.size()==0){ 
        IPHolder newIP = new IPHolder(); 
        newIP.setIp(getIP(line)); 
        newIP.setCount(0); 
        ips.add(newIP); 
       } 
       for(int j=0;j<ips.size();j++){ 
        if(ips.get(j).getIp().equals(getIP(line))){ 
         ips.get(j).setCount(ips.get(j).getCount()+1); 
        }else{ 
         IPHolder newIP = new IPHolder(); 
         newIP.setIp(getIP(line)); 
         newIP.setCount(0); 
         ips.add(newIP); 
        } 
       } 
       if(counter % 1000 == 0){System.out.println(counter+", "+ips.size());} 
       counter+=1; 
      } 
     } 
    } finally {br.close();} 
    for(int k=0;k<ips.size();k++){ 
     System.out.println("ip, count: "+ips.get(k).getIp()+" , "+ips.get(k).getCount()); 
    } 
} 

public String getIP(String ipString){//extracts an ip from a string if the string contains an ip 
    String IPADDRESS_PATTERN = 
    "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"; 

    Pattern pattern = Pattern.compile(IPADDRESS_PATTERN); 
    Matcher matcher = pattern.matcher(ipString); 
    if (matcher.find()) { 
     return matcher.group(); 
    } 
    else{ 
     return "0.0.0.0"; 
    } 
} 

Класс держатель:

public class IPHolder { 

    private String ip; 
    private int count; 

    public String getIp(){return ip;} 
    public void setIp(String i){ip=i;} 

    public int getCount(){return count;} 
    public void setCount(int ct){count=ct;} 
} 
+0

A [ 'Map'] (https://docs.oracle.com/javase/7/docs/api/java/util/Map.html), вероятно, что вам нужно (ключ = IP, значение = count). Гуава ['Multiset'] (https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset) - необычная альтернатива –

+0

@RC. как бы выглядел код с картой? – CodeMed

+0

Ссылка на 'Multiset' имеет пример карты –

ответ

1

Ключевое слово для поиска является HashMap в этом случае. HashMap - это список пар ключей (в данном случае пары ips и их счет).

"192.168.1.12" - 12 
"192.168.1.13" - 17 
"192.168.1.14" - 9 

и так далее. Это намного проще в использовании и доступе, чем всегда перебирать массив объектов контейнера, чтобы узнать, есть ли уже контейнер для этого ip или нет.

BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(/*Your file */))); 

HashMap<String, Integer> occurrences = new HashMap<String, Integer>(); 

String line = null; 

while((line = br.readLine()) != null) { 

    // Iterate over lines and search for ip address patterns 
    String[] addressesFoundInLine = ...; 


    for(String ip: addressesFoundInLine) { 

     // Did you already have that address in your file earlier? If yes, increase its counter by 
     if(occurrences.containsKey(ip)) 
      occurrences.put(ip, occurrences.get(ip)+1); 

     // If not, create a new entry for this address 
     else 
      occurrences.put(ip, 1); 
    } 
} 


// TreeMaps are automatically orered if their elements implement 'Comparable' which is the case for strings and integers 
TreeMap<Integer, ArrayList<String>> turnedAround = new TreeMap<Integer, ArrayList<String>>(); 

Set<Entry<String, Integer>> es = occurrences.entrySet(); 

// Switch keys and values of HashMap and create a new TreeMap (in case there are two ips with the same count, add them to a list) 
for(Entry<String, Integer> en: es) { 

    if(turnedAround.containsKey(en.getValue()))   
     turnedAround.get(en.getValue()).add((String) en.getKey()); 
    else { 
     ArrayList<String> ips = new ArrayList<String>(); 
     ips.add(en.getKey()); 
     turnedAround.put(en.getValue(), ips); 
    } 

} 

// Print out the values (if there are two ips with the same counts they are printed out without an special order, that would require another sorting step) 
for(Entry<Integer, ArrayList<String>> entry: turnedAround.entrySet()) {   
    for(String s: entry.getValue()) 
     System.out.println(s + " - " + entry.getKey());   
} 

В моем случае вывод был следующий:

192.168.1.19 - 4 
192.168.1.18 - 7 
192.168.1.27 - 19 
192.168.1.13 - 19 
192.168.1.12 - 28 

Я ответил this question полчаса назад, и я думаю, что это именно то, что вы ищете, так что если вам нужна какая-то пример кода , взгляните на это.

+0

Благодарим вас и +1 за это. Как изменяется код, если я хочу распечатать его отсортированным в порядке возрастания счетчиков? – CodeMed

+0

Отредактировал мой код. Протестировал новую часть, и она работает. Я также отредактировал первую часть, чтобы исправить две небольшие проблемы (int> Integer как тип для HashMap). Сортировка содержимого HashMaps не так проста, как вы могли бы подумать, поскольку созданные HashMaps будут доступны очень быстро и, следовательно, пропустите процесс сортировки. Если у вас есть другие вопросы, не стесняйтесь спрашивать. :) – Phiwa

0

Вот код, который использует HashMap для хранения IP-адресов и регулярного выражения для их соответствия в каждой строке. Он использует try-with-resources для автоматического закрытия файла.

EDIT: Я добавил код для печати в порядке убывания, как вы сказали в другом ответе.

void read(String fileName) throws IOException { 
    //Step 1 find and register IPs and store their occurence counts 
    HashMap<String, Integer> ipAddressCounts = new HashMap<>(); 
    try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)))) { 
     Pattern findIPAddrPattern = Pattern.compile("((\\d+.){3}\\d+)"); 
     String line; 
     while ((line = br.readLine()) != null) { 
      Matcher matcher = findIPAddrPattern.matcher(line); 
      while (matcher.find()) { 
       String ipAddr = matcher.group(0); 
       if (ipAddressCounts.get(ipAddr) == null) { 
        ipAddressCounts.put(ipAddr, 1); 
       } 
       else { 
        ipAddressCounts.put(ipAddr, ipAddressCounts.get(ipAddr) + 1); 
       } 
      } 
     } 
    } 

    //Step 2 reverse the map to store IPs by their frequency 
    HashMap<Integer, HashSet<String>> countToAddrs = new HashMap<>(); 
    for (Map.Entry<String, Integer> entry : ipAddressCounts.entrySet()) { 
     Integer count = entry.getValue(); 
     if (countToAddrs.get(count) == null) 
      countToAddrs.put(count, new HashSet<String>()); 
     countToAddrs.get(count).add(entry.getKey()); 
    } 

    //Step 3 sort and print the ip addreses, most frequent first 
    ArrayList<Integer> allCounts = new ArrayList<>(countToAddrs.keySet()); 
    Collections.sort(allCounts, Collections.reverseOrder()); 
    for (Integer count : allCounts) { 
     for (String ip : countToAddrs.get(count)) { 
      System.out.println("ip, count: " + ip + " , " + count); 
     } 
    } 
} 
Смежные вопросы