使用 Stream-Java 8 替换文件中的文本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35234474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replace text in a file using Stream- Java 8
提问by A.R.K.S
I'm trying to write an API to replace all the lines containing a certain substring with a different string in a text file.
我正在尝试编写一个 API 来用文本文件中的不同字符串替换包含某个子字符串的所有行。
I'm using Java 8 stream to filter the lines which contains the given pattern. I'm having problem with the file write part.
我正在使用 Java 8 流来过滤包含给定模式的行。我的文件写入部分有问题。
Files.lines(targetFile).filter(line -> line.contains(plainTextPattern)).parallel()
.map(line-> line.replaceAll(plainTextPattern, replaceWith)).parallel();
Above code reads the file line-wise, filters the lines that match the pattern and replaces with the give string and gives back a stream of strings which has only the replaced lines.
上面的代码逐行读取文件,过滤与模式匹配的行并用给定的字符串替换,并返回一个只有替换行的字符串流。
We need to write these lines back to file. Since we lose the stream once the pipeline ends, I appended the following to the pipeline:
我们需要将这些行写回文件。由于一旦管道结束我们就会丢失流,因此我将以下内容附加到管道中:
.forEach(line -> {
try {
Files.write(targetFile, line.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
}
I was hoping it would write to the file only the modified (since it is in the pipeline) line and keep the other lines untouched.
我希望它只会将修改后的(因为它在管道中)行写入文件,并保持其他行不变。
But it seems to truncate the file for each line in the file and keep only the last processed line and deletes all the lines that were not matched in the pipeline.
但它似乎为文件中的每一行截断文件,只保留最后处理的行并删除管道中所有不匹配的行。
Is there something I'm missing about handling files using streams?
使用流处理文件有什么我遗漏的吗?
回答by Louis Wasserman
Using filter
eliminates anything that doesn't match the filter from the stream. (Additionally, for what it's worth, a) you only need to use parallel
once, b) parallel
isn't that effective on streams coming from I/O sources, c) it's almost never a good idea to use parallel
until you've actually tried it non-parallel and found it too slow.)
使用filter
从流中消除了与过滤器不匹配的任何内容。(此外,就其价值而言,a)您只需要使用parallel
一次,b)parallel
对来自 I/O 源的流不是那么有效,c)parallel
在您实际尝试之前使用它几乎从来都不是一个好主意不平行,发现它太慢了。)
That said: there's no need to filter out the lines that match the pattern if you're going to do a replaceAll
. Your code should look like this:
也就是说:如果您要执行replaceAll
. 您的代码应如下所示:
try (Stream<String> lines = Files.lines(targetFile)) {
List<String> replaced = lines
.map(line-> line.replaceAll(plainTextPattern, replaceWith))
.collect(Collectors.toList());
Files.write(targetFile, replaced);
}
回答by Sleiman Jneidi
So sorry to tell you that this is not how files work. If you want to write to the middle of a file, you need to have RandomAccess
; Get a FilePointer
, seek, that pointer, and write from there.
很抱歉地告诉您,这不是文件的工作方式。如果要写入文件的中间,则需要具有RandomAccess
; 获取一个FilePointer
,寻找,那个指针,然后从那里写。
This holds if the size of data you want write is equal to the size of data you want to overwrite. If this is not the case, you have to copy the tail of the file to a temp buffer and append it to the text you wish to write.
如果您要写入的数据大小等于您要覆盖的数据大小,这将成立。如果不是这种情况,您必须将文件的尾部复制到临时缓冲区并将其附加到您要写入的文本中。
And btw, parallelStreams
on IO
bound tasks is often a bad idea.
和顺便说一句,parallelStreams
在IO
密集型任务往往是一个坏主意。