ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## [文件读写](https://lingcoder.gitee.io/onjava8/#/book/17-Files?id=%e6%96%87%e4%bb%b6%e8%af%bb%e5%86%99) 此时,我们可以对路径和目录做任何事情。 现在让我们看一下操纵文件本身的内容。 如果一个文件很“小”,也就是说“它运行得足够快且占用内存小”,那么`java.nio.file.Files`类中的实用程序将帮助你轻松读写文本和二进制文件。 `Files.readAllLines()`一次读取整个文件(因此,“小”文件很有必要),产生一个`List<String>`。 对于示例文件,我们将重用`streams/Cheese.dat`: ~~~ // files/ListOfLines.java import java.util.*; import java.nio.file.*; public class ListOfLines { public static void main(String[] args) throws Exception { Files.readAllLines( Paths.get("../streams/Cheese.dat")) .stream() .filter(line -> !line.startsWith("//")) .map(line -> line.substring(0, line.length()/2)) .forEach(System.out::println); } } /* Output: Not much of a cheese Finest in the And what leads you Well, it's It's certainly uncon */ ~~~ 跳过注释行,其余的内容每行只打印一半。 这实现起来很简单:你只需将`Path`传递给`readAllLines()`(以前的 java 实现这个功能很复杂)。`readAllLines()`有一个重载版本,包含一个`Charset`参数来存储文件的 Unicode 编码。 `Files.write()`被重载以写入`byte`数组或任何`Iterable`对象(它也有`Charset`选项): ~~~ // files/Writing.java import java.util.*; import java.nio.file.*; public class Writing { static Random rand = new Random(47); static final int SIZE = 1000; public static void main(String[] args) throws Exception { // Write bytes to a file: byte[] bytes = new byte[SIZE]; rand.nextBytes(bytes); Files.write(Paths.get("bytes.dat"), bytes); System.out.println("bytes.dat: " + Files.size(Paths.get("bytes.dat"))); // Write an iterable to a file: List<String> lines = Files.readAllLines( Paths.get("../streams/Cheese.dat")); Files.write(Paths.get("Cheese.txt"), lines); System.out.println("Cheese.txt: " + Files.size(Paths.get("Cheese.txt"))); } } /* Output: bytes.dat: 1000 Cheese.txt: 199 */ ~~~ 我们使用`Random`来创建一个随机的`byte`数组; 你可以看到生成的文件大小是 1000。 一个`List`被写入文件,任何`Iterable`对象也可以这么做。 如果文件大小有问题怎么办? 比如说: 1. 文件太大,如果你一次性读完整个文件,你可能会耗尽内存。 2. 您只需要在文件的中途工作以获得所需的结果,因此读取整个文件会浪费时间。 `Files.lines()`方便地将文件转换为行的`Stream`: ~~~ // files/ReadLineStream.java import java.nio.file.*; public class ReadLineStream { public static void main(String[] args) throws Exception { Files.lines(Paths.get("PathInfo.java")) .skip(13) .findFirst() .ifPresent(System.out::println); } } /* Output: show("RegularFile", Files.isRegularFile(p)); */ ~~~ 这对本章中第一个示例代码做了流式处理,跳过 13 行,然后选择下一行并将其打印出来。 `Files.lines()`对于把文件处理行的传入流时非常有用,但是如果你想在`Stream`中读取,处理或写入怎么办?这就需要稍微复杂的代码: ~~~ // files/StreamInAndOut.java import java.io.*; import java.nio.file.*; import java.util.stream.*; public class StreamInAndOut { public static void main(String[] args) { try( Stream<String> input = Files.lines(Paths.get("StreamInAndOut.java")); PrintWriter output = new PrintWriter("StreamInAndOut.txt") ) { input.map(String::toUpperCase) .forEachOrdered(output::println); } catch(Exception e) { throw new RuntimeException(e); } } } ~~~ 因为我们在同一个块中执行所有操作,所以这两个文件都可以在相同的 try-with-resources 语句中打开。`PrintWriter`是一个旧式的`java.io`类,允许你“打印”到一个文件,所以它是这个应用的理想选择。如果你看一下`StreamInAndOut.txt`,你会发现它里面的内容确实是大写的。