使用 Files.lines 修改文件
Modify file using Files.lines
我想读入文件并用新文本替换一些文本。使用 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);
Files.write(..., Iterable, ...)
方法在这里看起来很诱人,但是将 Stream 转换为 Iterable 会使这变得很麻烦。它也是来自 Iterable 的 "pulls",这有点奇怪。如果可以在 forEach
.
之类的范围内将文件写入方法用作流的终端操作,那将更有意义
不幸的是,大多数写入的东西都会抛出 IOException
,这是 forEach
期望的 Consumer
功能接口所不允许的。但是 PrintWriter 不同。至少,它的写法不会抛出checked exception,虽然开一个还是可以抛出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);
}
我想读入文件并用新文本替换一些文本。使用 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);
Files.write(..., Iterable, ...)
方法在这里看起来很诱人,但是将 Stream 转换为 Iterable 会使这变得很麻烦。它也是来自 Iterable 的 "pulls",这有点奇怪。如果可以在 forEach
.
不幸的是,大多数写入的东西都会抛出 IOException
,这是 forEach
期望的 Consumer
功能接口所不允许的。但是 PrintWriter 不同。至少,它的写法不会抛出checked exception,虽然开一个还是可以抛出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);
}