Java面試通關手冊(Java學習指南)github地址(歡迎star和pull):github.com/Snailclimb/…
歷史回顧:
其他高贊文章:
一 檔案I/O基石:Path
Java7中檔案IO發生了很大的變化,專門引入了很多新的類來取代原來的基於java.io.File的檔案IO操作方式:
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;·
......等等
複製程式碼
我們將從下面幾個方面來學習Path類:
- 建立一個Path
- File和Path之間的轉換,File和URI之間的轉換
- 獲取Path的相關資訊
- 移除Path中的冗餘項
1 建立一個Path
建立Path例項可以通過 Paths工具類 的 get()方法:
//使用絕對路徑
Path path= Paths.get("c:\\data\\myfile.txt");
複製程式碼
//使用相對路徑
Path path = Paths.get("/home/jakobjenkov/myfile.txt");
複製程式碼
下面這種建立方式和上面等效:
Path path = FileSystems.getDefault().getPath("c:\\data\\myfile.txt");
複製程式碼
2 File和Path之間的轉換,File和URI之間的轉換
File file = new File("C:/my.ini");
Path p1 = file.toPath();
p1.toFile();
file.toURI();
複製程式碼
3 獲取Path的相關資訊
//使用Paths工具類的get()方法建立
Path path = Paths.get("D:\\XMind\\bcl-java.txt");
/* //使用FileSystems工具類建立
Path path2 = FileSystems.getDefault().getPath("c:\\data\\myfile.txt");*/
System.out.println("檔名:" + path.getFileName());
System.out.println("名稱元素的數量:" + path.getNameCount());
System.out.println("父路徑:" + path.getParent());
System.out.println("根路徑:" + path.getRoot());
System.out.println("是否是絕對路徑:" + path.isAbsolute());
//startsWith()方法的引數既可以是字串也可以是Path物件
System.out.println("是否是以為給定的路徑D:開始:" + path.startsWith("D:\\") );
System.out.println("該路徑的字串形式:" + path.toString());
複製程式碼
結果:
檔名:bcl-java.txt
名稱元素的數量:2
父路徑:D:\XMind
根路徑:D:\
是否是絕對路徑:true
是否是以為給定的路徑D:開始:true
該路徑的字串形式:D:\XMind\bcl-java.txt
複製程式碼
4 移除冗餘項
某些時候在我們需要處理的Path路徑中可能會有一個或兩個點
- .表示的是當前目錄
- ..表示父目錄或者說是上一級目錄:
下面通過例項來演示一下使用Path類的normalize()和toRealPath()方法把.和..去除。
- normalize() : 返回一個路徑,該路徑是冗餘名稱元素的消除。
- toRealPath() : 融合了toAbsolutePath()方法和normalize()方法
//.表示的是當前目錄
Path currentDir = Paths.get(".");
System.out.println(currentDir.toAbsolutePath());//輸出C:\Users\Administrator\NIODemo\.
Path currentDir2 = Paths.get(".\\NIODemo.iml");
System.out.println("原始路徑格式:"+currentDir2.toAbsolutePath());
System.out.println("執行normalize()方法之後:"+currentDir2.toAbsolutePath().normalize());
System.out.println("執行toRealPath()方法之後:"+currentDir2.toRealPath());
//..表示父目錄或者說是上一級目錄:
Path currentDir3 = Paths.get("..");
System.out.println("原始路徑格式:"+currentDir3.toAbsolutePath());
System.out.println("執行normalize()方法之後:"+currentDir3.toAbsolutePath().normalize());
System.out.println("執行toRealPath()方法之後:"+currentDir3.toRealPath());
複製程式碼
結果:
C:\Users\Administrator\NIODemo\.
原始路徑格式:C:\Users\Administrator\NIODemo\.\NIODemo.iml
執行normalize()方法之後:C:\Users\Administrator\NIODemo\NIODemo.iml
執行toRealPath()方法之後:C:\Users\Administrator\NIODemo\NIODemo.iml
原始路徑格式:C:\Users\Administrator\NIODemo\..
執行normalize()方法之後:C:\Users\Administrator
執行toRealPath()方法之後:C:\Users\Administrator
複製程式碼
二 擁抱Files類
Java NIO中的Files類(java.nio.file.Files)提供了多種操作檔案系統中檔案的方法。本節教程將覆蓋大部分方法。Files類包含了很多方法,所以如果本文沒有提到的你也可以直接查詢JavaDoc文件。
java.nio.file.Files類是和java.nio.file.Path相結合使用的
1 檢查給定的Path在檔案系統中是否存在
通過 Files.exists() 檢測檔案路徑是否存在:
Path path = Paths.get("D:\\XMind\\bcl-java.txt");
boolean pathExists =
Files.exists(path,
new LinkOption[]{LinkOption.NOFOLLOW_LINKS});
System.out.println(pathExists);//true
複製程式碼
注意Files.exists()的的第二個引數。它是一個陣列,這個引數直接影響到Files.exists()如何確定一個路徑是否存在。在本例中,這個陣列內包含了LinkOptions.NOFOLLOW_LINKS,表示檢測時不包含符號連結檔案。
2 建立檔案/資料夾
- 建立檔案:
通過 Files.createFile() 建立檔案,
Path target2 = Paths.get("C:\\mystuff.txt");
try {
if(!Files.exists(target2))
Files.createFile(target2);
} catch (IOException e) {
e.printStackTrace();
}
複製程式碼
-
建立資料夾:
- 通過 Files.createDirectory() 建立資料夾
- 通過 Files.createDirectories() 建立資料夾
Files.createDirectories()會首先建立所有不存在的父目錄來建立目錄,而Files.createDirectory()方法只是建立目錄,如果它的上級目錄不存在就會報錯。比如下面的程式使用Files.createDirectory() 方法建立就會報錯,這是因為我的D盤下沒有data資料夾,加入存在data資料夾的話則沒問題。
Path path = Paths.get("D://data//test"); try { Path newDir = Files.createDirectories(path); } catch(FileAlreadyExistsException e){ // the directory already exists. } catch (IOException e) { //something else went wrong e.printStackTrace(); } 複製程式碼
3 刪除檔案或目錄
通過 Files.delete()方法 可以刪除一個檔案或目錄:
Path path = Paths.get("data/subdir/logging-moved.properties");
try {
Files.delete(path);
} catch (IOException e) {
//deleting file failed
e.printStackTrace();
}
複製程式碼
4 把一個檔案從一個地址複製到另一個位置
通過Files.copy()方法可以吧一個檔案從一個地址複製到另一個位置
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();
}
複製程式碼
copy操作還可可以強制覆蓋已經存在的目標檔案,只需要將上面的copy()方法改為如下格式:
Files.copy(sourcePath, destinationPath,
StandardCopyOption.REPLACE_EXISTING);
複製程式碼
5 獲取檔案屬性
Path path = Paths.get("D:\\XMind\\bcl-java.txt");
System.out.println(Files.getLastModifiedTime(path));
System.out.println(Files.size(path));
System.out.println(Files.isSymbolicLink(path));
System.out.println(Files.isDirectory(path));
System.out.println(Files.readAttributes(path, "*"));
複製程式碼
結果:
2016-05-18T08:01:44Z
18934
false
false
{lastAccessTime=2017-04-12T01:42:21.149351Z, lastModifiedTime=2016-05-18T08:01:44Z, size=18934, creationTime=2017-04-12T01:42:21.149351Z, isSymbolicLink=false, isRegularFile=true, fil
複製程式碼
6 遍歷一個資料夾
Path dir = Paths.get("D:\\Java");
try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)){
for(Path e : stream){
System.out.println(e.getFileName());
}
}catch(IOException e){
}
複製程式碼
結果:
apache-maven-3.5.0
Eclipse
intellij idea
Jar
JDK
MarvenRespository
MyEclipse 2017 CI
Nodejs
RedisDesktopManager
solr-7.2.1
複製程式碼
上面是遍歷單個目錄,它不會遍歷整個目錄。遍歷整個目錄需要使用:Files.walkFileTree().Files.walkFileTree()方法具有遞迴遍歷目錄的功能。
7 遍歷整個檔案目錄:
walkFileTree接受一個Path和FileVisitor作為引數。Path物件是需要遍歷的目錄,FileVistor則會在每次遍歷中被呼叫。
FileVisitor需要呼叫方自行實現,然後作為引數傳入walkFileTree().FileVisitor的每個方法會在遍歷過程中被呼叫多次。如果不需要處理每個方法,那麼可以繼承它的預設實現類SimpleFileVisitor,它將所有的介面做了空實現。
public class WorkFileTree {
public static void main(String[] args) throws IOException{
Path startingDir = Paths.get("D:\\apache-tomcat-9.0.0.M17");
List<Path> result = new LinkedList<Path>();
Files.walkFileTree(startingDir, new FindJavaVisitor(result));
System.out.println("result.size()=" + result.size());
}
private static class FindJavaVisitor extends SimpleFileVisitor<Path>{
private List<Path> result;
public FindJavaVisitor(List<Path> result){
this.result = result;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
if(file.toString().endsWith(".java")){
result.add(file.getFileName());
}
return FileVisitResult.CONTINUE;
}
}
}
複製程式碼
上面這個例子輸出了我的D:\apache-tomcat-9.0.0.M17也就是我的Tomcat安裝目錄下以.java結尾檔案的數量。
結果:
result.size()=4
複製程式碼
Files類真的很強大,除了我講的這些操作之外還有其他很多操作比如:讀取和設定檔案許可權、更新檔案所有者等等操作。
我這裡就介紹這麼多了,如果想要詳細瞭解的可以自行查閱官方文件或者相關書籍。
歡迎關注我的微信公眾號:"Java面試通關手冊"(一個有溫度的微信公眾號,期待與你共同進步~~~堅持原創,分享美文,分享各種Java學習資源):