使用Files.lines修改文件

bri*_*ian 20 java-8 java-stream

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

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

在那里的某个地方,我想要一个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"));
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

编辑:我已经做到这一点,它的工作原理.我尝试使用过滤器,也许这不是必需的.

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

Stu*_*rks 43

这个Files.write(..., Iterable, ...)方法看起来很诱人,但将Stream转换为Iterable会让这很麻烦.它也从Iterable"拉"出来,这有点奇怪.如果文件写入方法可以用作流的终端操作,那将更有意义forEach.

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

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

注意使用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);
}
Run Code Online (Sandbox Code Playgroud)