從 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);
}
}
}