2010-06-10 18 views
14

Mam duże pliki tekstowe, które zamierzam wstępnie dopasowywać po kolei (tylko przechwytywanie, nie zastępowanie). Myślę, że nie jest dobrym pomysłem przechowywanie całego pliku w pamięci, a raczej używanie Reader.Wykonywanie wyrażeń regularnych w strumieniu

Co wiem o danych wejściowych jest to, że jeśli jest dopasowanie, nie będzie ono obejmować więcej niż 5 linii. Więc moim pomysłem było posiadanie jakiegoś bufora, który utrzymuje te 5 linii, lub tak, zrobić pierwsze wyszukiwanie i kontynuować. Ale musi "wiedzieć", gdzie zakończył się mecz regex, aby to zadziałało. np. jeśli mecz kończy się na linii 2, powinien rozpocząć następne wyszukiwanie od tego miejsca. Czy można zrobić coś takiego w sposób wydajny?

Odpowiedz

26

można użyć Scanner i metoda findWithinHorizon:

Scanner s = new Scanner(new File("thefile")); 
String nextMatch = s.findWithinHorizon(yourPattern, 0); 

z interfejsu API na findWithinHorizon:

Jeśli horyzont jest 0, to horyzont jest ignorowany i ta metoda nadal przeszukiwać wejście szukającego określonego wzorca bez powiązania. W takim przypadku może buforować wszystkie dane wejściowe szukające wzorca.

Na marginesie: Podczas dopasowywania na wielu liniach, warto spojrzeć na stałe Pattern.MULTILINE i Pattern.DOTALL.

+0

+1; i przeczytaj API, aby zrozumieć, w jaki sposób 'Scanner' radzi sobie z' IOException'. – polygenelubricants

2

Streamflyer potrafi stosować wyrażenia regularne w strumieniach znaków.

Pamiętaj, że jestem autorem.

-5

Z Java8 można to zrobić bardzo prosto i ewentualnie w parallel-

// Create a pattern-matcher 
private static final Pattern emailRegex = Pattern.compile("([^,]+?)@([^,]+)"); 

//Read content of a file 
String fileContent = Files.lines(Path.get("/home/testFile.txt") 
           .collect(Collector.join(" ")); 
// Apply the pattern-matcher 
List<String> results = matcherStream(emailRegex.matcher(fileContent)) 
          .map(b -> b[2]) 
          .collect(Collector.toList())); 

Innym sposobem może być -

List<String> results = Files.lines(Path.get("/home/testFile.txt") 
           .parallelStream() 
           .forEach(s -> "use regex") 
           .collect(Collector.toList()); 
+0

wziąłeś tę treść z innej odpowiedzi, nie odwołując się do niej (http://stackoverflow.com/a/24663422/1902625) i nie zostało to nawet zrobione całkowicie. Metoda 'matcherStream' nie jest zdefiniowana. – haventchecked

0
import java.io.*; //BufferedReader //FileReader //FileWriter //PrintWriter 
import java.io.IOException; 
import java.util.Scanner; 
import java.util.regex.*; 

public class ScannerReader { 

    public static void main(String[] args) { 

     try { 
      ReadDataFromFileTestRegex("[A-Za-z_0-9-%$!][email protected][A-Za-z_0-9-%!$]+\\.[A-Za-z]{2,4}", 
             "C:\\Users\\Admin\\Desktop\\TextFiles\\Emails.txt", 
             "C:\\Users\\Admin\\Desktop\\TextFiles\\\\output.txt"); 
     } catch (Exception e) { 
      System.out.println("File is not found"); 
      e.printStackTrace(); 
     }  
    } 

    public static void ReadDataFromFileTestRegex (String theReg, String FileToRead, String FileToWrite) throws Exception { 

     PrintWriter Pout = new PrintWriter(FileToWrite);    
     Pattern p = Pattern.compile(theReg); 
     BufferedReader br = new BufferedReader (new FileReader(FileToRead)); 
     String line = br.readLine();  
     while (line != null) {   
      Matcher m = p.matcher(line); 
      while (m.find()) { 
       if (m.group().length() != 0) { 
        System.out.println(m.group().trim()); 
       }    
       System.out.println("Start index: " + m.start()); 
       System.out.println("End index : " + m.end()); 
       Pout.println(m.group()); //print the result to the output file 
      } 
      line = br.readLine(); 
     } 
     Pout.flush(); 
     br.close(); 
     Pout.close(); 
    } 
} 
+0

Czy możesz poprawić swój obiecujący post, dodając przykład użycia kodu i przykładowy wynik? – Stephan

2

Realizacja java regularnych silnika ekspresji wygląda nadają się do przesyłania strumieniowego przetwarzanie.

Wolałbym promować inne podejście oparte na "kombinatorach pochodnych".

Badacz Matt Might opublikował stosowne posty o "kombinatorów pochodnych" na swoim blogu i proponuje wdrożenie Scala tutaj:

po mojej stronie, to sukces w celu poprawy tej implementacji poprzez dodanie "zdolności" do przechwytywania, ale uważam, że może to mieć znaczący wpływ na zużycie pamięci.

Powiązane problemy