【问题标题】:Modify file using Files.lines使用 Files.lines 修改文件
【发布时间】:2015-04-14 18:49:38
【问题描述】:

我想读入一个文件并用新文本替换一些文本。使用 asm 和 int 21h 会很简单,但我想使用新的 java 8 流。

    Files.write(outf.toPath(), 
        (Iterable<String>)Files.lines(inf)::iterator,
        CREATE, WRITE, TRUNCATE_EXISTING);

我想要一个lines.replace("/*replace me*/","new Code()\n");。新行是因为我想测试在某处插入一段代码。

这是一个播放示例,它不能按我的意愿工作,但可以编译。我只需要一种方法来截取迭代器中的行,并用代码块替换某些短语。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import static java.nio.file.StandardOpenOption.*;
import java.util.Arrays;
import java.util.stream.Stream;

public class FileStreamTest {

    public static void main(String[] args) {
        String[] ss = new String[]{"hi","pls","help","me"};
        Stream<String> stream = Arrays.stream(ss);

        try {
            Files.write(Paths.get("tmp.txt"),
                    (Iterable<String>)stream::iterator,
                    CREATE, WRITE, TRUNCATE_EXISTING);
        } catch (IOException ex) {}

//// I'd like to hook this next part into Files.write part./////
        //reset stream
        stream = Arrays.stream(ss);
        Iterable<String> it = stream::iterator;
        //I'd like to replace some text before writing to the file
        for (String s : it){
            System.out.println(s.replace("me", "my\nreal\nname"));
        }
    }

}

编辑:我已经做到了这一点并且它有效。我正在尝试使用过滤器,也许它不是真的必要。

        Files.write(Paths.get("tmp.txt"),
                 (Iterable<String>)(stream.map((s) -> {
                    return s.replace("me", "my\nreal\nname");
                }))::iterator,
                CREATE, WRITE, TRUNCATE_EXISTING);

【问题讨论】:

  • 我很困惑。您想从文件中读取一些文本行,将这些行替换为其他一些文本(可能通过正则表达式),然后将这些行写回文件?对吗?
  • 没错。也许我会在问题中更好地解释。

标签: java-8 java-stream


【解决方案1】:

Files.write(..., Iterable, ...) 方法在这里看起来很诱人,但是将 Stream 转换为 Iterable 会变得很麻烦。它还从 Iterable 中“拉取”,这有点奇怪。如果文件写入方法可以用作流的终端操作,那就更有意义了,比如forEach

不幸的是,大多数写的东西都会抛出IOException,这是forEach 所期望的Consumer 功能接口所不允许的。但 PrintWriter 不同。至少,它的写法不会抛出已检查的异常,虽然打开还是可以抛出IOException。以下是它的使用方法。

Stream<String> stream = ... ;
try (PrintWriter pw = new PrintWriter("output.txt", "UTF-8")) {
    stream.map(s -> s.replaceAll("foo", "bar"))
          .forEachOrdered(pw::println);
}

注意forEachOrdered 的使用,它按照读取的顺序打印输出行,这大概就是您想要的!

如果您正在从输入文件中读取行,修改它们,然后将它们写入输出文件,则将两个文件放在同一个 try-with-resources 语句中是合理的:

try (Stream<String> input = Files.lines(Paths.get("input.txt"));
     PrintWriter output = new PrintWriter("output.txt", "UTF-8"))
{
    input.map(s -> s.replaceAll("foo", "bar"))
         .forEachOrdered(output::println);
}

【讨论】:

  • 谢谢,这比我的要干净得多,是的,我正在读取输入文件。
猜你喜欢
  • 2014-06-10
  • 2019-07-17
  • 2019-04-25
  • 2013-05-18
  • 2012-09-06
  • 1970-01-01
  • 2018-10-05
  • 2020-03-18
  • 2011-08-04
相关资源
最近更新 更多