用来定位文件系统中文件的对象,它代表了依赖于系统的文件路径。
路径代表了一系列由系统分隔符分隔的文件和目录组成的层次结构。根组件作为层次结构的顶层也可以用路径来表示。离根目录最远的元素名是文件或目录名,另外的元素名表示为目录。路径可以表示为根目录、根目录与子目录或相对目录,如果一个路径由一个空元素构成,该路径被称为空路径,使用空路径访问一个文件相当于使用文件系统的缺省目录来访问那个文件。通过Path中的getFileName()、getParent()、getRoot()和subpath()来访问路径组件或一系列元素名。
除了访问路径组件,路径也定义了resolve()和resolveSibling()来组合路径,relativize()用来组合2个路径成一个相对路径,也可以通过compared()、startsWith()和endWith()来比较路径。
该接口扩展了Watchable接口,通过路径来定位的目录能使用WatchService(也就是实现了该接口的对象)来进行注册,用于监视该目录中的目录项。
文件访问
Files类使用路径来操控文件、目录和另外的文件类型。例如假定我们想创建一个BufferedReader的对象来读取“access.log”文件,该文件位于“logs”目录下,该目录是一个相对目录,使用了UTF-8的编码方式。
Path path=FileSystems.getDefault().getPath(“logs”,”access.log”);
BufferReader reader=Files.newBufferedReader(path,StandardCharsets.UTF_8);
互操作性
与缺省的provider相关的Paths通常能与java.nio.File类进行互操作,而用其它provider创建的Paths不可能与java.nio.File所表示的抽象路径名来进行互操作。可以使用toPath()通过转换的抽象路径名来获得Path,这个Path能用来操控文件就像java.nio.File对象操控文件一样。此外,可以使用toFile()来把一个字符串路径表示成一个文件
并发
这个接口的实现是不可变,对于多线程的并发来讲是安全的。
说明:路径对象主要用来指定文件或目录的位置,当路径对象被创建时候,需要提供给它一系列的名字(也可以仅单独一个名字),路径接口中除了toRealPath()外的其它方法都用于操控路径本身,而没有实际访问文件系统,因此我们把这种操作又称为基于句法的操作(Syntactic Operation)。
Java Code
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.Properties;
public class PathTestDemo {
public static void main(String[] args) throws IOException {
FileSystem fileSystem=FileSystems.getDefault();
System.out.println(fileSystem);
//getProperties()会得到一个系统属性的哈希表(HashTable)
Properties property=System.getProperties();
//利用这个集合的stringPropertyName()会得到一个字符串作为属性名的键集Set<Key>
for(String str:property.stringPropertyNames()){
System.out.format("属性名%s对应的属性值为:%s%n", str,property.getProperty(str));
}
/*要想得到单个属性的值只需要传递相应的字符串属性名给getProperty()方法即可
*比较有用属性名的如"user.dir"表示用户当前目录、"user.home"表示用户缺省根目录
* user.country、java.class.path等等
*/
String property1=System.getProperty("file.separator");
String property2=System.getProperty("line.separator");
String property3=System.getProperty("path.separator");
String property4=System.getProperty("file.encoding");
System.out.format("文件分隔符为%s,行分隔符为%s,路径分隔符为%s,"
+ "开发平台文件使用的编码为%s%n", property1,property2,property3,property4);
Path path=fileSystem.getPath("testPath");//等价于Path path=Paths.get("testPath");
System.out.println(path.toString());
//以依赖文件系统的实现方式来解析路径,如果文件系统不可得到就会抛出异常
System.out.println(path.toAbsolutePath());
//注意:Path方法基本上都是基于所给的路径字符串形式来进行解析,不会真正访问文件系统
//所以得到的路径与实际路径会有差别。
System.out.println(path.getFileName());
System.out.println(path.getName(0));
System.out.println(path.getNameCount());
System.out.println(path.getParent());
System.out.println(path.getRoot());
//toRealPath()要对实际的目录来进行操作,如果该目录不存在会抛出IO异常
//如果传递参数true给方法toRealPath(true),那么表明该路径容许解析Symbolic links
System.out.println(path.toRealPath(LinkOption.NOFOLLOW_LINKS));
System.out.println(path.toFile());
System.out.println(path.toUri());
Path path1=Paths.get("myPath", "toMyPath");
System.out.println(path1);
System.out.println(path1.toAbsolutePath());
/*
* thisPath.relativize(OtherPath)总会得到一个thisPath到OtherPath的相对路径
* 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);
*/
/*下面方法都是由2个路径合成一个路径,只是最终的目的不一样
* relativize()方法合并路径p1和p2来得到一个从p1到p2的路径,或者得到一个从p2到p1的路径,
* 结果取决于谁是调用者,如果p1调用方法relativize(),那么结果是前者,否则为后者。
*
* p1.resolve(p2)方法合并路径p1和p2,如果该p2包含根目录组件(也就是目录开始有"/"或"\"),那么返回结果为p2表示的目录
* 如果p2为空目录,返回p1的目录。排除以上情况最后的结果就是合并2个字符串成一个新目录
* 例如: p1的路径为 e:\a\b\c p2的路径为:b\c 那么p1.resolve(p2)的结果为 e:\a\b\c\b\c
*
* p1.resolveSibling(p2)其目的是使p1的最远端的子目录或文件成为p2的兄弟目录或文件。例如:
* p1的路径为e:\a\b\c p2的路径为 d\e\f,c为p1最远端的目录或文件,调用该方法的目的是使
* c与整个p2成为兄弟关系,也就说在b文件夹下包含"c"与"d\e\f",注意这些都是基于语义,并不是实际存在
* 如果p2包含根目录或根组件目录(其意义同上),也就是说,p2不可能与c成为兄弟关系,那么结果直接返回p2
* 当p1只有c并且p2为空才返回空路径
*/
Path path2=Paths.get("e:/a/b/c");
Path path3=Paths.get("b/c");
System.out.format("path2相对于path3解析后的结果路径为:%s%n",path2.resolve(path3));
System.out.println(path.relativize(path1));
System.out.println(path.resolve(path1));
Path path4=Paths.get("e:/a/b/c");
Path path5=Paths.get("d/e/f");
System.out.println(path4.resolveSibling(path5));
System.out.println(path5.resolveSibling(path4));
//得到路径的迭代器,用于遍历组成路径的所有元素
Iterator<Path> itp=path.iterator();
while(itp.hasNext()){
System.out.println(itp.next());
}
FileSystem fileSystem1=path.getFileSystem();
//FileSystem的方法getRootDirectories()会得到该系统上所有卷(或者分区)的集合
Iterator it=fileSystem1.getFileStores().iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
//FileSystem的方法getRootDirectories()会得到该系统上所有卷(或者分区)的盘符的集合
Iterator it1=fileSystem1.getRootDirectories().iterator();
while(it1.hasNext())
{
System.out.println(it1.next());
}
}
}