Java NIO files
java.nio.file.Files
類提供了許多操作檔案的方法,它們往往和Path類合作使用。
1.Files.exits()
Files#exits()
方法檢查一個Path是否存在於當前的檔案系統中。假如我們直接使用Path例項的相關方法,那麼一個不存在的檔案可能會被建立,如果我們想避免這種情況的發生,那麼可以先使用Files#extis()
來進行一下檢查。
Path path = Paths.get("data/logging.properties");
boolean pathExists =
Files.exists(path,
new LinkOption[]({LinkOption.NOFOLLOW_LINKS});
顯然,exits()
方法有兩個引數,第一個是要檢查的path,第二個是exits()
方法的選項陣列。如LinkOption.NOFOLLOW_LINKS
代表不允許跟隨檔案系統中的符號連結來確定路徑是否存在。
2.Files.createDirectory()
Files#createDirectory()
方法利用Path建立一個新的目錄。
Path path = Paths.get("data/subdir");
try {
Path newDir = Files.createDirectory(path);
} catch(FileAlreadyExistsException e){
// the directory already exists.
} catch (IOException e) {
//something else went wrong
e.printStackTrace();
}
通過上面的示例一眼就可以看出這個方法是幹嘛用的,另外就是注意一下通過丟擲異常來對不同的情況進行處理。
注:假如父目錄不存在,可能丟擲IOException
異常。
3.Files.copy()
Files#copy()
方法將檔案從一個path複製到另一個。
Path sourcePath = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");
try {
Files.copy(sourcePath, destinationPath);
} catch(FileAlreadyExistsException e) {
//destination file already exists
} catch (IOException e) {
//something else went wrong
e.printStackTrace();
}
功能太明顯了。如果目標檔案已存在,會丟擲FileAlreadyExistsException
,如果試圖將檔案複製到不存在的目錄,會丟擲IOException
。
但也可以要求Files#copy()
方法強制覆蓋可能存在的檔案。
Path sourcePath = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");
try {
Files.copy(sourcePath, destinationPath,
StandardCopyOption.REPLACE_EXISTING);// 這個引數
} catch(FileAlreadyExistsException e) {
//destination file already exists
} catch (IOException e) {
//something else went wrong
e.printStackTrace();
}
在copy方法的引數列表中加上這個StandardCopyOption.REPLACE_EXISTING
,可以在目標檔案存在時強制覆蓋。
4.FIles.move()
Files#move()
方法將檔案從一個path移動到另一個path。同時可以設定目標的檔名,也就是說不僅可以實現移動功能,也可以實現重新命名或移動+重新命名。
Path sourcePath = Paths.get("data/logging-copy.properties");
Path destinationPath = Paths.get("data/subdir/logging-moved.properties");
try {
Files.move(sourcePath, destinationPath,
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
//moving file failed.
e.printStackTrace();
}
功能顯而易見,StandardCopyOption.REPLACE_EXISTING
引數的意義和copy
方法中的一樣。
5.Files.delete()
Files#delete()
方法可以刪除一個檔案或資料夾。
Path path = Paths.get("data/subdir/logging-moved.properties");
try {
Files.delete(path);
} catch (IOException e) {
//deleting file failed
e.printStackTrace();
}
6.Files.walkFileTree()
Files.walkFileTree()
方法可以遞迴遍歷目錄樹。它使用一個Path
和一個FileVisitor
作為引數。
首先先展示一下FileVisitor
介面
public interface FileVisitor {
public FileVisitResult preVisitDirectory(
Path dir, BasicFileAttributes attrs) throws IOException;
public FileVisitResult visitFile(
Path file, BasicFileAttributes attrs) throws IOException;
public FileVisitResult visitFileFailed(
Path file, IOException exc) throws IOException;
public FileVisitResult postVisitDirectory(
Path dir, IOException exc) throws IOException {
}
Files.walkFileTree()
方法需要一個FileVisitor
的實現類作為引數,實現FileVisitor
介面就需要實現上述方法。如果不想做特殊實現或者只想實現一部分,可以繼承SimpleFileVisitor
類,它其中有對FileVisitor
的方法的預設實現。
下面是示例:
Files.walkFileTree(path, new FileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("pre visit dir:" + dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("visit file: " + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
System.out.println("visit file failed: " + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
System.out.println("post visit directory: " + dir);
return FileVisitResult.CONTINUE;
}
});
這些方法在遍歷的不同時間被呼叫
preVisitDirectory()
方法在訪問任何目錄前被呼叫。postVisitDirectory()
方法在訪問任何目錄後被呼叫。visitFile()
方法在訪問任何檔案時被呼叫。visitFileFailed()
在訪問任何檔案失敗時被呼叫。(比如沒許可權)
每個方法返回;一個FileVisitResult
列舉,這些返回指決定了遍歷如何進行。包括
CONTINUE
。表示遍歷將繼續正常進行。TERMINATE
。表示檔案遍歷將終止。SKIP_SIBLINGS
。表示檔案遍歷將繼續,但不在訪問此檔案/目錄的同級檔案/目錄。SKIP_SUBTREE
。表示檔案遍歷將繼續,但不再訪問此目錄內的檔案。
下面是一個通過walkFileTree()
方法尋找名字為README.txt
的檔案的示例。注意這裡的FileVisitor
是繼承SimpleFileVisitor
的,不過重寫了visitFile
方法。
Path rootPath = Paths.get("data");
String fileToFind = File.separator + "README.txt";
try {
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String fileString = file.toAbsolutePath().toString();
//System.out.println("pathString = " + fileString);
if(fileString.endsWith(fileToFind)){
System.out.println("file found at path: " + file.toAbsolutePath());
return FileVisitResult.TERMINATE;
}
return FileVisitResult.CONTINUE;
}
});
} catch(IOException e){
e.printStackTrace();
}
下面是一個通過walkFileTree()
方法刪除名字為README.txt
的檔案的示例。注意這裡的FileVisitor
是繼承SimpleFileVisitor
的,不過重寫了visitFile
方法和postVisitDirectory
方法。
Files#delete()
方法僅在目錄為空時刪除目錄,但下面的程式碼可以遞迴刪除。
Path rootPath = Paths.get("data/to-delete");
try {
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("delete file: " + file.toString());
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
System.out.println("delete dir: " + dir.toString());
return FileVisitResult.CONTINUE;
}
});
} catch(IOException e){
e.printStackTrace();
}
7.其他方法
Files類中還有許多其他方法,可以自己去看API。