从 java.io.File 迁移到 Java 7 NIO(java.nio.file.Path)
这些示例假设你已经知道 Java 7 的 NIO 通常是什么,并且你习惯使用 java.io.File
编写代码。使用这些示例可以快速找到更多以 NIO 为中心的迁移文档。
Java 7 的 NIO 还有很多东西,比如内存映射文件, 或者使用 FileSystem 打开 ZIP 或 JAR 文件 。这些示例仅涵盖有限数量的基本用例。
作为一项基本规则,如果你习惯使用 java.io.File
实例方法执行文件系统读/写操作,你将在 java.nio.file.Files
中找到它作为静态方法。
指向一条路
// -> IO
File file = new File("io.txt");
// -> NIO
Path path = Paths.get("nio.txt");
相对于另一条路径的路径
// Forward slashes can be used in place of backslashes even on a Windows operating system
// -> IO
File folder = new File("C:/");
File fileInFolder = new File(folder, "io.txt");
// -> NIO
Path directory = Paths.get("C:/");
Path pathInDirectory = directory.resolve("nio.txt");
将文件从/转换为 Path 以用于库
// -> IO to NIO
Path pathFromFile = new File("io.txt").toPath();
// -> NIO to IO
File fileFromPath = Paths.get("nio.txt").toFile();
检查文件是否存在,如果存在则将其删除
// -> IO
if (file.exists()) {
boolean deleted = file.delete();
if (!deleted) {
throw new IOException("Unable to delete file");
}
}
// -> NIO
Files.deleteIfExists(path);
通过 OutputStream 写入文件
有几种方法可以使用 NIO 编写和读取文件,用于不同的性能和内存限制,可读性和用例,例如 FileChannel
, Files.write(Path path, byte\[\] bytes, OpenOption... options)
……在这个例子中,只涵盖了 OutputStream
,但我们强烈建议你学习内存映射文件和 java.nio.file.Files
中提供的各种静态方法。
List<String> lines = Arrays.asList(
String.valueOf(Calendar.getInstance().getTimeInMillis()),
"line one",
"line two");
// -> IO
if (file.exists()) {
// Note: Not atomic
throw new IOException("File already exists");
}
try (FileOutputStream outputStream = new FileOutputStream(file)) {
for (String line : lines) {
outputStream.write((line + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
}
}
// -> NIO
try (OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE_NEW)) {
for (String line : lines) {
outputStream.write((line + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
}
}
迭代文件夹中的每个文件
// -> IO
for (File selectedFile : folder.listFiles()) {
// Note: Depending on the number of files in the directory folder.listFiles() may take a long time to return
System.out.println((selectedFile.isDirectory() ? "d" : "f") + " " + selectedFile.getAbsolutePath());
}
// -> NIO
Files.walkFileTree(directory, EnumSet.noneOf(FileVisitOption.class), 1, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path selectedPath, BasicFileAttributes attrs) throws IOException {
System.out.println("d " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path selectedPath, BasicFileAttributes attrs) throws IOException {
System.out.println("f " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
});
递归文件夹迭代
// -> IO
recurseFolder(folder);
// -> NIO
// Note: Symbolic links are NOT followed unless explicitly passed as an argument to Files.walkFileTree
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("d " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path selectedPath, BasicFileAttributes attrs) throws IOException {
System.out.println("f " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
});
private static void recurseFolder(File folder) {
for (File selectedFile : folder.listFiles()) {
System.out.println((selectedFile.isDirectory() ? "d" : "f") + " " + selectedFile.getAbsolutePath());
if (selectedFile.isDirectory()) {
// Note: Symbolic links are followed
recurseFolder(selectedFile);
}
}
}