在流上执行正则表达式

我有一些大文本文件,我将进行连续匹配(只是捕获,而不是替换)。 我认为将整个文件保存在内存中并不是一个好主意,而是使用Reader

我对输入的了解是,如果匹配,它不会超过5行。 所以我的想法是有一些缓冲区只保留这5行,或者左右,进行第一次搜索,然后继续。 但它必须“知道”正则表达式匹配结束的位置才能实现。 例如,如果匹配在第2行结束,它应该从这里开始下一次搜索。 是否有可能以有效的方式做这样的事情?

您可以使用ScannerfindWithinHorizon方法:

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

来自api on findWithinHorizon

如果horizo​​n为0,则忽略horizo​​n,此方法继续搜索输入,查找指定的模式而不绑定。 在这种情况下,它可以缓冲搜索模式的所有输入。

旁注:在多行匹配时,您可能需要查看常量Pattern.MULTILINEPattern.DOTALL

Streamflyer能够在字符流上应用正则表达式。

请注意,我是它的作者。

正则表达式引擎的java实现看起来不适合流处理。

我宁愿主张另一种以“衍生组合者”为基础的方法。

研究员Matt Might在他的博客上发表了关于“衍生组合器”的相关post,并建议在这里实施Scala:

在我这边,我通过添加一些“捕获”能力成功地改进了这个实现,但我觉得它可能会对内存消耗产生重大影响。

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

使用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 results = matcherStream(emailRegex.matcher(fileContent)) .map(b -> b[2]) .collect(Collector.toList())); 

另一种方式可以是 –

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