我在磁盘上有一个(文本)文件,我需要将其读入带有 Reader 对象的库中。
在阅读此文件时,我想对数据执行正则表达式字符串替换。
我当前的解决方案是将整个文件作为一个字符串读入内存,进行字符串替换,然后为此字符串创建一个 StringReader 并将其作为 Reader 返回到库中。
这是可行的,但是对于大文件(尤其是在多个线程中运行),性能是一个问题。
我想做的是让它一次从文件中读取每一行,替换这个子字符串,然后默默地返回给 Reader 的使用者 - 但我不知道如何做到这一点。
有更好的方法来完成这个任务吗?
我正在使用 Java 7
我当前解决方案的一个示例如下 - 从“文件”读取,将所有“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
}
}
Update
下面是一个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();
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)