java - Java - Reader 流中的动态字符串替换
问题描述
我在磁盘上有一个(文本)文件,我需要将它读入一个带有 Reader 对象的库。
在阅读此文件时,我想对数据执行正则表达式字符串替换。
我目前的解决方案是将整个文件作为一个字符串读入内存,进行字符串替换,然后为这个字符串创建一个 StringReader 并将其作为 Reader 传递回库中。
这可行,但是对于大文件(尤其是在多个线程中运行),性能是一个问题。
我想做的是让它一次读取文件中的每一行,替换这个子字符串,然后默默地返回给阅读器的消费者——但我想不出该怎么做。
有没有更好的方法来完成这项任务?
我正在使用 Java 7
下面是我当前解决方案的一个示例 - 从“文件”读取,用“b”替换所有“a”,然后将流传递给消费者。
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
流的用户呈现一个界面。
在内部,原始流被包装在 a 中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();
}
}
推荐阅读
- angular - Angular Material 组件未正确显示
- vba - 如何复制/粘贴部分行
- php - Wordpress 页面上的自定义搜索查询不起作用
- tensorflow - 手动绘制边界框时的问题
- matlab - 使用 linspace 时出错(第 22 行)输入必须是标量
- python - 如何从数据框行中的字典中提取值
- html - 为什么我有幽灵边距?
- tabulate - ModuleNotFoundError:没有名为“制表”的模块
- javascript - 无法将项目推入 React Js 中的列表
- python - 如何从 Python Lambda 函数中访问 TaskToken