Выполнение регулярных выражений в потоке - PullRequest
15 голосов
/ 10 июня 2010

У меня есть несколько больших текстовых файлов, по которым я собираюсь выполнить последовательное сопоставление (просто захват, а не замена).Я думаю, что не очень хорошая идея хранить весь файл в памяти, а использовать Reader.

. Что я знаю о входных данных, так это то, что если есть совпадение, оно не будет охватывать5 строк.Так что моя идея заключалась в том, чтобы иметь какой-то буфер, который просто хранит эти 5 строк или около того, выполнить первый поиск и продолжить.Но он должен «знать», где закончилось совпадение с регулярным выражением, чтобы это сработало.например, если совпадение заканчивается в строке 2, отсюда следует начать следующий поиск.Можно ли сделать что-то подобное таким эффективным способом?

Ответы [ 5 ]

26 голосов
/ 10 июня 2010

Вы можете использовать Scanner и findWithinHorizon метод:

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

Из API на findWithinHorizon:

Если горизонт равен 0, то горизонт игнорируется, и этот метод продолжает поиск по входу в поисках указанного шаблона без привязки.В этом случае он может буферизовать все входные данные для поиска шаблона.

Примечание: при сопоставлении по нескольким строкам вы можете посмотреть на константы Pattern.MULTILINE и Pattern.DOTALL.

2 голосов
/ 19 ноября 2016

Java-реализация механизма регулярных выражений выглядит неподходящей для потоковой обработки.

Я бы предпочел другой подход, основанный на «производных комбинаторах».

Исследователь Мэтт Майт опубликовал соответствующие посты о «производных комбинаторах» в своем блоге и предлагает здесь реализацию Scala:

Со своей стороны, мне удалось улучшить эту реализацию, добавив некоторую способность «захвата», но я чувствую, что это может оказать значительное влияние на потребление памяти.

2 голосов
/ 12 сентября 2013

Streamflyer может применять регулярные выражения к символьным потокам.

Обратите внимание, что я являюсь его автором.

0 голосов
/ 01 апреля 2016
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-%$!]+@[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 голосов
/ 25 июня 2015

С Java8 вы можете сделать это довольно просто и, возможно, параллельно -

// 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()));

Другой способ может быть -

List<String> results = Files.lines(Path.get("/home/testFile.txt")
                              .parallelStream()
                              .forEach(s -> "use regex")
                              .collect(Collector.toList());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...