使用Stream-Java 8替换文件中的文本

A.R*_*K.S 7 java regex file-io java-8 java-stream

我正在尝试编写一个API,用文本文件中的不同字符串替换包含某个子字符串的所有行.

我正在使用Java 8流来过滤包含给定模式的行.我有文件写入部分的问题.

Files.lines(targetFile).filter(line -> line.contains(plainTextPattern)).parallel()
      .map(line-> line.replaceAll(plainTextPattern, replaceWith)).parallel();
Run Code Online (Sandbox Code Playgroud)

上面的代码按行读取文件,过滤与模式匹配的行并替换为give字符串,并返回仅包含替换行的字符串流.

我们需要将这些行写回文件.由于我们在管道结束后丢失了流,因此我将以下内容添加到管道中:

.forEach(line -> {
try {
            Files.write(targetFile, line.toString().getBytes());
} catch (IOException e) {
  e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

我希望它只会写入修改后的文件(因为它在管道中),并保持其他行不变.

但它似乎截断文件中每一行的文件,并仅保留最后一个处理的行并删除管道中未匹配的所有行.

有没有我在使用流处理文件时缺少的东西?

Lou*_*man 19

使用可以filter消除与流中的过滤器不匹配的任何内容.(另外,对于它的价值,a)你只需要使用parallel一次,b)parallel对来自I/O源的流不是那么有效,c)parallel在你真正尝试它之前使用它几乎不是一个好主意不平行,发现它太慢了.)

这就是说:如果你要做的话,没有必要过滤出与模式相匹配的线条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);
}
Run Code Online (Sandbox Code Playgroud)


Sle*_*idi 6

很抱歉告诉你这不是文件的工作方式.如果你想写入文件的中间,你需要RandomAccess; 获取FilePointer,搜索,指针,并从那里写.

如果要写入的数据大小等于要覆盖的数据大小,则此操作成立.如果不是这种情况,则必须将文件的尾部复制到临时缓冲区并将其附加到要写入的文本中.

顺便说parallelStreams一下,IO绑定任务往往是个坏主意.