本文章主要包括如下几个章节:类介绍、Path实例获取和文件路径管理。文件路径管理中,主要介绍了Path中定义的主要方法。
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}.
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);
根据前面可以知道,Path接口主要是用来管理文件路径的,所以文件路径管理涉及的主要也是Path中的方法。当然,这些基本上也涵盖了Path中的绝大多数方法。
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();
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
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
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
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