File IO(NIO.2):路徑類 和 路徑操作

路徑類

Java SE 7版本中引入的Path類是java.nio.file包的主要入口點之一。如果您的應用程序使用文件I / O,您將需要了解此類的強大功能。 

版本注意:如果您有使用java.io.File的JDK7之前的代碼,則仍然可以使用File.toPath方法來利用Path類功能。有關詳細信息,請參閱傳統文件I / O代碼。 

顧名思義,Path類是文件系統中路徑的編程表示形式。路徑對象包含用於構建路徑的文件名和目錄列表,用於檢查,定位和操作文件。 

路徑實例反映了底層平臺。在Solaris OS中,路徑使用Solaris語法(/ home / joe / foo),而在Microsoft Windows中,路徑使用Windows語法(C:\ home \ joe \ foo)。路徑與系統無關。您不能將Solaris與Solaris文件系統進行比較,並期望它與Windows文件系統中的路徑相匹配,即使目錄結構相同,並且兩個實例都找到相同的相對文件。 

與Path相對應的文件或目錄可能不存在。您可以創建一個Path實例並以各種方式進行操作:您可以附加它,提取它,並將其與其他路徑進行比較。在適當的時候,您可以使用Files類中的方法檢查與Path對應的文件的存在,創建文件,打開它,刪除它,更改其權限等。 

下一頁將詳細介紹Path類。

路徑操作

簡介

Path類包括可用於獲取有關路徑,路徑訪問元素,將路徑轉換爲其他窗體或提取路徑部分的信息的各種方法。還有一些方法可以匹配路徑字符串和方法來刪除路徑中的冗餘。這個課程解決了這些Path方法,有時被稱爲語法操作,因爲它們在路徑本身上操作,並且不訪問文件系統。

創建一個路徑

路徑實例包含用於指定文件或目錄位置的信息。在定義的時候,路徑被提供有一系列一個或多個名稱。可能包含根元素或文件名,但不是必需的。路徑可能只包含一個目錄或文件名。 您可以通過使用路徑中的以下幫助類中的方法之一輕鬆創建一個Path對象(注意複數):
Path p1 = Paths.get("/tmp/foo");
Path p2 = Paths.get(args[0]);
Path p3 = Paths.get(URI.create("file:///Users/joe/FileTest.java"));
Paths.get方法是以下代碼的縮寫:
Path p4 = FileSystems.getDefault().getPath("/users/sally");

以下示例創建/u/joe/logs/foo.log,假設您的主目錄是/ u / joe,或者C:\ joe \ logs \ foo.log(如果您在Windows上)。

Path p5 = Paths.get(System.getProperty("user.home"),"logs", "foo.log");

檢索路徑信息

您可以將路徑視爲將這些名稱元素作爲序列存儲。目錄結構中的最高元素將位於索引0.目錄結構中的最低元素將位於索引[n-1],其中n是路徑中名稱元素的數量。方法可用於使用這些索引檢索單個元素或路徑的子序列。 
本課程中的示例使用以下目錄結構。


以下代碼片段定義了一個Path實例,然後調用幾個方法來獲取有關該路徑的信息:
// None of these methods requires that the file corresponding
// to the Path exists.
// Microsoft Windows syntax
Path path = Paths.get("C:\\home\\joe\\foo");

// Solaris syntax
Path path = Paths.get("/home/joe/foo");

System.out.format("toString: %s%n", path.toString());
System.out.format("getFileName: %s%n", path.getFileName());
System.out.format("getName(0): %s%n", path.getName(0));
System.out.format("getNameCount: %d%n", path.getNameCount());
System.out.format("subpath(0,2): %s%n", path.subpath(0,2));
System.out.format("getParent: %s%n", path.getParent());
System.out.format("getRoot: %s%n", path.getRoot());
以下是Windows和Solaris操作系統的輸出:

上一個示例顯示絕對路徑的輸出。在以下示例中,指定了相對路徑:
// Solaris syntax
Path path = Paths.get("sally/bar");
or
// Microsoft Windows syntax
Path path = Paths.get("sally\\bar");
以下是Windows和Solaris OS的輸出:

從路徑中刪除冗餘數據

許多文件系統使用“.” 表示當前目錄的符號,“..”表示父目錄。 您可能會遇到路徑包含冗餘目錄信息的情況。 也許服務器配置爲將其日誌文件保存在“/ dir / logs /”中。 目錄,並且您想要刪除尾隨的“/”。 
以下示例都包括冗餘:
/home/./joe/foo
/home/sally/../joe/foo
normalize方法刪除任何冗餘元素,其中包括任何“.”或“目錄/ ..”出現。以上兩個例子都歸結爲/ home / joe / foo。 
重要的是要注意,normalize在文件系統清理路徑時不檢查。這是一個純粹的句法操作。在第二個例子中,如果sally是一個符號鏈接,則刪除sally / ..可能會導致一個不再定位目標文件的路徑。 要清理路徑,同時確保結果找到正確的文件,可以使用toRealPath方法。該方法在下一節“轉換路徑”中進行了說明。

轉換路徑

您可以使用三種方法來轉換路徑。如果您需要將路徑轉換爲可以從瀏覽器打開的字符串,則可以使用toUri。例如:
Path p1 = Paths.get("/home/logfile");
// Result is file:///home/logfile
System.out.format("%s%n", p1.toUri());
toAbsolutePath方法將路徑轉換爲絕對路徑。如果傳入路徑已經是絕對路徑,則返回相同的路徑對象。在處理用戶輸入的文件名時,toAbsolutePath方法非常有用。例如:
public class FileTest {
    public static void main(String[] args) {

        if (args.length < 1) {
            System.out.println("usage: FileTest file");
            System.exit(-1);
        }

        // Converts the input string to a Path object.
        Path inputPath = Paths.get(args[0]);

        // Converts the input Path
        // to an absolute path.
        // Generally, this means prepending
        // the current working
        // directory.  If this example
        // were called like this:
        //     java FileTest foo
        // the getRoot and getParent methods
        // would return null
        // on the original "inputPath"
        // instance.  Invoking getRoot and
        // getParent on the "fullPath"
        // instance returns expected values.
        Path fullPath = inputPath.toAbsolutePath();
    }
}
toAbsolutePath方法轉換用戶輸入並返回一個在查詢時返回有用值的路徑。該文件不需要存在,以使此方法正常工作。 
toRealPath方法返回現有文件的真實路徑。該方法可以執行多個操作: 
1,如果true傳遞給此方法,並且文件系統支持符號鏈接,則此方法可以解析路徑中的任何符號鏈接。 
2,如果路徑是相對的,則返回絕對路徑。 
3,如果路徑包含任何冗餘元素,它將返回一個刪除這些元素的路徑。
 如果文件不存在或無法訪問,此方法將拋出異常。當您想處理這些情況時,您可以捕獲異常。例如:
try {
    Path fp = path.toRealPath();
} catch (NoSuchFileException x) {
    System.err.format("%s: no such" + " file or directory%n", path);
    // Logic for case when file doesn't exist.
} catch (IOException x) {
    System.err.format("%s%n", x);
    // Logic for other sort of file error.
}

聯合兩個路徑

你可以組合路徑,通過使用resolve方法。 通過訪問部分路徑——不包括根節點,並且這個部分路徑可以被添加到原始路徑
例如:思考以下代碼:
// Solaris
Path p1 = Paths.get("/home/joe/foo");
// Result is /home/joe/foo/bar
System.out.format("%s%n", p1.resolve("bar"));
或者
// Microsoft Windows
Path p1 = Paths.get("C:\\home\\joe\\foo");
// Result is C:\home\joe\foo\bar
System.out.format("%s%n", p1.resolve("bar"));
將絕對路徑傳遞給resolve方法返回傳入路徑:
// Result is /home/joe
Paths.get("foo").resolve("/home/joe");

在兩個路徑之間創建一個新的路徑

一個很常見的需求是:當你在使用IO代碼時,需要從一個文件系統的路徑構建一個新的路徑到另一個地方。你可以使用relativize方法,這個方法構建了從原來的路徑和終點位置的路徑中構建一個路徑,這個新的路徑對於原始路徑來說,是相對的:
例如:思考下面被定義爲 Joe 和 Sally 的相對路徑:
Path p1 = Paths.get("joe");
Path p2 = Paths.get("sally");
對於其他信息而言,假設 Joe 和 Sally是兄妹,這意味着這個節點在樹結構中有着同等的等級。 要想通過 Joe找到Sally,你可能需要首先找到這個父節點,然後找到Sally。
// Result is ../sally
Path p1_to_p2 = p1.relativize(p2);
// Result is ../joe
Path p2_to_p1 = p2.relativize(p1);
再看一個略微複雜的例子:
Path p1 = Paths.get("home");
Path p3 = Paths.get("home/sally/bar");
// Result is sally/bar
Path p1_to_p3 = p1.relativize(p3);
// Result is ../..
Path p3_to_p1 = p3.relativize(p1);
在這個例子中,兩個路徑共享了一個節點:home。 從home找到了bar,首先需要找到一個等級(home),然後再查找下一個等級找到Sally,最後再找到bar。從bar要找到home,需要向上查找兩個等級。
不能創建一個相對路徑,如果這個路徑包含根節點。如果這個路徑包含根節點,只有系統有創建這個相對路徑的能力。

這個Copy 的遞歸例子,使用了relativize 和 resolve 方法。

比較兩個路徑

Path 類支持equals方法,這個方法讓你可以檢測兩個路徑是否一致。這個startsWith和endWith方法,使你可以檢測任意一個以部分字符開始或結束的路徑。這些方法使用起來都很簡單,例如:
Path path = ...;
Path otherPath = ...;
Path beginning = Paths.get("/home");
Path ending = Paths.get("foo");

if (path.equals(otherPath)) {
    // equality logic here
} else if (path.startsWith(beginning)) {
    // path begins with "/home"
} else if (path.endsWith(ending)) {
    // path ends with "foo"
}

Path類實現了Iterable接口,iterator方法返回一個對象,而這個對象讓你可以遍歷路徑中的所有節點名稱。第一個被返回的節點,是離目錄樹最近的根節點。下面的代碼簡單的遍歷了一個路徑,並打印每一個節點的名稱:
Path path = ...;
for (Path name: path) {
    System.out.println(name);
}
Path類同樣實現了comparable接口,你可以比較路徑對象通過comparaTo方法,這個方法對於排序也同樣有用。
你也可以將一個Path對象放入一個collection ,查看集合 教程瞭解更多有用的功能。
當你想確認兩個路徑對象是同一個文件時,你可以使用isSameFile方法,這個方法被描述在:檢測兩個路徑是否存在於同一個文件

發佈了306 篇原創文章 · 獲贊 230 · 訪問量 57萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章