当前位置: 首页 > 工具软件 > :path > 使用案例 >

Java NIO文件路径管理:Path类和Paths类

赵刚豪
2023-12-01

    本文章主要包括如下几个章节:类介绍、Path实例获取和文件路径管理。文件路径管理中,主要介绍了Path中定义的主要方法。

1、类的介绍

    Path接口 是JDK1.7中定义的接口,主要用来在文件系统中定位文件,通常表示系统相关的文件路径。JDK中的介绍:An object that may be used to locate a file in a file system. It will typically represent a system dependent file path.

    Paths类 是JDK1.7中定义的静态工具类,用来根据String格式的路径或者URI返回Path的实例。JDK中的介绍:This class consists exclusively of static methods that return a {@link Path} by converting a path string or {@link URI}.

2、Path实例的获取

    Path是接口,实例不能通过new关键字直接去构建;而Path的实现类,官方并不想暴露出来给用户使用,所以我们应该通过其他途径去获取Path的实例。

    这里,我总结了4个方向去获取Path的实例:

    1)根据字符串格式的路径获取:使用Paths工具类中的get方法去获取,方法的参数是1个或1个以上的String,Paths会自动根据参数中的字符串对路径做拼接。另外,两个点".."表示的是路径向上回退一级。

    2)根据URI获取:使用Paths的get(URI url)方法获取。

    3)根据File的实例进行转换:File中定义了实例方法toPath(),可以将File实例转换为Path的实例。

    4)从对其他Path实例的操作中获取:这个相关的方法就有很多了,例如Path自己的getParent()、normalize()等,或者Files中的诸多create、copy、walk等等多个系列的很多方法。这里就不一一列举了。

    代码实例:

Path path;
// 1. From String
path = Paths.get(System.getProperty("user.dir"), "..", "data")

// 2. From URI
path = Paths.get(Main.class.getClassLoader().getResource("test.txt").toURI());

// 3. From File
path = new File(System.getProperty("user.dir") + File.separator + "data").toPath();

// 4. From other Path instances: there are many functions can do that in Files.class, for example:
Path path1 = Paths.get(System.getProperty("user.dir"), "data");
path = Files.createDirectory(path1);

3、文件路径管理(Path的主要方法)

    根据前面可以知道,Path接口主要是用来管理文件路径的,所以文件路径管理涉及的主要也是Path中的方法。当然,这些基本上也涵盖了Path中的绝大多数方法。

Part 1:

    1)path.getFileName():获取文件、目录或者其他类型文件(下文统统用文件指代这几种情况的任一)的名称,返回值类型是Path。例如对于/users/nanxs/test构造的Path实例,返回的就是test对应的Path实例。

    2)path.getParent():获取文件的父路径的Path实例,例如对于/users/nanxs/test构造的Path实例,返回的就是/users/nanxs对应的Path实例。

    3)path.getName(int index)和path.getNameCount():分层拆分路径,例如对于/users/nanxs/test,getNameCount()返回的就是3,而对于path.getName(int index),当index分别为0~2时,得到的结果分别是users、nanxs和test。

    4)path.getRoot():获取根路径,例如对于Linux/Mac OS,根路径一般就是"/"。

    5)path.getFileSystem():获取文件系统。对FileSystem不熟悉的读者请参考:FileSystem类

    代码实例:

    Path path = Paths.get(System.getProperty("user.dir"), "data/test.txt");

    // 1. get name of the file or direction
    System.out.println("file name: " + path.getFileName());

    console: file name: test.txt

    // 2. get absolute path of parent of the file
    System.out.println("parent path: " + path.getParent());

    console: parent path: /Users/nanxs/TestCode/Tests/data

    // 3. get path of any appointed level
    for (int i = 0; i < path.getNameCount(); i++) {
      System.out.println(String.format("name of count(%d) is: %s", i, path.getName(i).toString()));
    }

    console: 
        name of count(0) is: Users
        name of count(1) is: nanxs
        name of count(2) is: TestCode
        name of count(3) is: Tests
        name of count(4) is: data
        name of count(5) is: test.txt

    // 4. get root path
    System.out.println("root: " + path.getRoot());

    console: root: /

    // 5. get file system:
    FileSystem fileSystem = path.getFileSystem();

Part 2:

    6)path.startsWith(Path other)或path.startsWith(String other):判断path的是不是以other开头的。对于/users/nanxs/test,不是start with users,而是start with "/"。

    7)path.endsWith(Path other)或path.endsWith(String other):判断path的是不是以other结束的。对于/users/nanxs/test.txt,就是以test.txt结束的。

    8)path.normalize():规范化文件路径,去除路径中多余的部分。对于/users/nanxs/test/../test2,规范化后得到的结果就是/users/nanxs/test2。

    代码示例:

    Path path = Paths.get(System.getProperty("user.dir"), "data/test.txt");
    Path path1 = Paths.get(path.getParent().toString(), "..", "data/test.txt");

    // 6. if the path of this file starts with (a String or a Path instance)
    System.out.println("start with: " + path.startsWith(path.getRoot()));
    System.out.println("start with: " + path.startsWith("/"));

    console: 
        start with: true
        start with: true

    // 7. if the path of this file ends with (a String or a Path instance)
    System.out.println("end with: " + path.endsWith(path.getFileName()));
    System.out.println("end with: " + path.endsWith("test.txt"));

    console: 
        end with: true
        end with: true

    // 8. get normalized path of file, that is to say, the path without redundancy element
    System.out.println("original path of path1: " + path1.getParent() + "/" + path1.getFileName());
    System.out.println("normalized path of path1: " + path1.normalize());

    console: 
        original path of path1: /Users/nanxs/TestCode/Tests/data/../data/test.txt
        normalized path of path1: /Users/nanxs/TestCode/Tests/data/test.txt

Part 3:

    9)Path示例之间的比较:

        a)path.equals(path1):两个路径完全相同时才会返回true,例如/users/nanxs/test/../test2和/users/nanxs/test2比较,得到的也是false。

        b)path.compareTo(path1):两个路径完全相同时才会返回0。否则:

            首先,从第一个字符开始比较,直到碰到第一个不一样的字符时,返回path的字符的ASCII码 - path1的字符的ASCII码的int值;

            然后,如果直到一个path的路径的字符已经比较到最后一位了,仍然没有找到差别,此时返回path的路径长度(即字符数量)- path1的路径长度。

        c)Files.isSameFile(path, path1):比较两个path是否找到相同的文件。代码执行的逻辑如下:

            首先,如果两个Path实例equals,则直接返回true;

            然后,如果两个Path实例来自于不同的FileSystemProvider,则直接返回false;

            最后,方法检查两个Path实例是否指向同一个文件。这时,取决于该FileSystemProvider的实现类的实现,有可能会要求访问两个文件。如果去访问文件,如果文件不存在,可能产生异常。

        JDK中的介绍:If both {@code Path} objects are {@link Path#equals(Object) equal} then this method returns {@code true} without checking if the file exists. If the two {@code Path} objects are associated with different providers then this method returns {@code false}. Otherwise, this method checks if both {@code Path} objects locate the same file, and depending on the implementation, may require to open or access both files.

    代码示例:

    Path path = Paths.get(System.getProperty("user.dir"), "data/test.txt");
    Path path1 = Paths.get(path.getParent().toString(), "..", "data/test.txt");
    Path path2 = Paths.get(System.getProperty("user.dir"), "data/tett.txt");

    // 9. compare with another Path instance
    System.out.println("compare with path1: " + path.equals(path1));
    System.out.println("compare with normalized path1: " + path.equals(path1.normalize()));
    System.out.println("compare with path1 using Files: " + Files.isSameFile(path, path1));
    System.out.println("compare to path1: " + path.compareTo(path1));
    System.out.println("compare to path2: " + path.compareTo(path2));
    System.out.println("compare to normalized path1: " + path.compareTo(path1.normalize()));

    console: 
        compare with path1: false
        compare with normalized path1: true
        compare with path1 using Files: true
        compare to path1: 70
        compare to path2: -1
        compare to normalized path1: 0

Part 4:

    10)path.isAbsolute():判断是否是绝对路径,即根据该路径是否能定位到实际的文件(不访问文件,只看是不是绝对路径,如果是绝对路径,即使文件不存在也会返回true)。

    11)path.iterator():返回迭代器,用来访问各级路径。

    代码示例:

    Path path = Paths.get(System.getProperty("user.dir"), "data/test.txt");

    // 10. is path absolute? In other words,  if we can locate a file or a dir without combination with other paths
    System.out.println("is path absolutely: " + path.isAbsolute());
    System.out.println("is path absolutely: " + path.getParent().isAbsolute());
    System.out.println("is path absolutely: " + path.getFileName().isAbsolute());

    console: 
        is path absolutely: true
        is path absolutely: true
        is path absolutely: false

    // 11. iterator of the array of levels of the path
    Iterator<Path> iterator = path.iterator();
    while (iterator.hasNext()){
      System.out.println("iterator: " + iterator.next());
    }

    console: 
        iterator: Users
        iterator: nanxs
        iterator: TestCode
        iterator: Tests
        iterator: data
        iterator: test.txt

Part 5:

    12)path.relativize(path1):返回一个相对路径,是基于path的path1的相对路径。例如path指定路径/users,path1指定路径/users/nanxs,那么返回的结果的路径就是nanxs。

    13)path.resolve(Path path1)或path.resolve(String path1):把当前路径当成父路径,把输入参数的路径当成子路径,得到一个新的路径。

    JDK中的介绍:If the {@code other} parameter is an {@link #isAbsolute() absolute} path then this method trivially returns {@code other}. If {@code other} is an <i>empty path</i> then this method trivially returns this path. Otherwise this method considers this path to be a directory and resolves the given path against this path. In the simplest case, the given path does not have a {@link #getRoot root} component, in which case this method <em>joins</em> the given path to this path and returns a resulting path that {@link #endsWith ends} with the given path. Where the given path has a root component then resolution is highly implementation dependent and therefore unspecified.

    代码示例:

    Path path = Paths.get(System.getProperty("user.dir"), "data/test.txt");

    // 12. get relative path with another Path instance based on this path
    Path relativePath = Paths.get(System.getProperty("user.dir")).relativize(path);
    System.out.println("relative path: " + relativePath);

    console: relative path: data/test.txt

    // 13. resolve another path with this path
    Path resolvedPath = path.getParent().getParent().resolve(path.getFileName());
    System.out.println("resolved path: " + resolvedPath);
    Path resolvedPath1 = path.getFileName().resolve(path.getParent().getFileName());
    System.out.println("resolved path: " + resolvedPath1);

    console: 
        resolved path: /Users/nanxs/TestCode/Tests/test.txt
        resolved path: test.txt/data

 

 类似资料: