我在磁盘上有一个(文本)文件,我需要将其读入一个带有 Reader 对象的库中。
在读取此文件时,我想对数据执行正则表达式字符串替换。
我目前的解决方案是将整个文件作为一个 String 读入内存,进行 String 替换,然后为该 String 创建一个 StringReader 并将其作为 Reader 传回库。
这可行,但是对于大文件(尤其是在多线程中运行),性能是个问题。
我想做的是让它一次从文件中读取每一行,替换这个子字符串,然后静静地返回给 Reader 的消费者——但我想不出该怎么做。
有没有更好的方法来完成这个任务?
我正在使用 Java 7
下面是我当前解决方案的示例 - 从"file"读取,将所有“a”替换为“b”,然后将 Stream 传递给消费者。
public void loadFile(final File file) throws Exception
{
final Pattern regexPattern = Pattern.compile("a");
final String replacementString = "b";
try (BufferedReader cleanedBufferedReader = new BufferedReader(new StringReader(replaceInBufferedReader(new BufferedReader(new FileReader(file)),
regexPattern, replacementString))))
{
new StreamSource(cleanedBufferedReader).doSomething();
}
}
private static String replaceInBufferedReader(final BufferedReader reader, final Pattern pattern, final String replacement) throws IOException
{
final StringBuilder builder = new StringBuilder();
String str;
while ((str = reader.readLine()) != null)
{
builder.append(str).append(System.lineSeparator());
}
return pattern.matcher(builder.toString()).replaceAll(replacement);
}
最佳答案
您只想子类化 BufferedReader。
class MyBufferedReader extends BufferedReader {
MyBufferedReader(Reader r) {
super(r);
}
@Override
String readLine() {
String line = super.readLine();
// perform replacement here
return line;
}
}
像往常一样打开您的文件,但不是将其包装在 BufferedReader 中,而是将其包装在您的子类中。
try ( Reader r = ...;
BufferedReader br = new MyBufferedReader(r)) {
String line;
while ((line = br.readLine()) != null) {
// use returned line
}
}
更新
下面是一个 Reader
,它允许您逐行替换输入流,同时仍然向用户呈现一个 Reader
界面流。
在内部,原始流被包装在 BufferedReader
中,一次读取一行。可以对已读取的行执行任何所需的转换。转换后的行然后变成 StringReader
。当流的用户调用任何 read(...)
操作时,请求被定向到缓冲的 StringReader
以满足。如果 StringReader
用完了字符,则加载并转换 BufferedReader
的下一行,以继续为 read(...)< 提供输入
.
abstract public class TranslatingReader extends Reader {
private BufferedReader input;
private StringReader output;
public TranslatingReader(Reader in) {
input = new BufferedReader(in);
output = new StringReader("");
}
abstract public String translate(String line);
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
int read = 0;
while (len > 0) {
int nchars = output.read(cbuf, off, len);
if (nchars == -1) {
String line = input.readLine();
if (line == null) {
break;
}
line = tranlate(line);
line += "\n"; // Add the newline which was removed by readLine()
output = new StringReader(line);
} else {
read += nchars;
off += nchars;
len -= nchars;
}
}
if (read == 0)
read = -1;
return read;
}
@Override
public void close() throws IOException {
input.close();
output.close();
}
}
关于Java - 读取器流中的动态字符串替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50799710/