我有一些大型文本文件需要进行连续匹配(只是捕获,不替换)。我认为将整个文件保存在内存中并不是一个好主意,而是要使用Reader
。
根据我的了解,如果有匹配项,它不会跨越超过5行。因此,我的想法是有一种缓冲区,仅保留这5行左右,进行第一次搜索,然后继续。但是它必须“知道”正则表达式匹配结束的地方才能这样做。例如,如果匹配在第2行结束,则应从此处开始下一次搜索。是否可能以一种高效的方式实现这种方法?
你可以使用 Scanner
和 findWithinHorizon
方法:
Scanner s = new Scanner(new File("thefile"));
String nextMatch = s.findWithinHorizon(yourPattern, 0);
来自API文档中findWithinHorizon
的说明:
如果horizon为0,则忽略horizon并继续搜索输入,寻找指定模式而不受限制。在这种情况下,它可能会缓冲所有输入以寻找该模式。
顺便提一下:当匹配多行时,您可能需要查看常量Pattern.MULTILINE
和Pattern.DOTALL
。
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();
}
}
Scanner.matchAll()
。它简化了我的代码。try(var scanner = new Scanner(Path.of(path), StandardCharsets.UTF_8)){
var result = scanner.findAll(PATTERN)
.map(MatchResult::group)
.collect(Collectors.toSet());
}
使用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());
Scanner
如何处理IOException
。 - polygenelubricants