Java7 NIO2 Path类

Java 从 1.0 开始就有了 Java IO 模型, 在 JDK 1.4 中添加了 NIO, 主要添加了非阻塞 IO 支持, Java 7 中, 增加了异步通道, 对本地文件系统添加了更多元数据支持 (File Attributes), 文件树遍历 (FileTreeWalker), 文件变化监测的 Watch Service 等功能.

Java.io.File 的不足

在 Java7 之前的版本中, Java.io.File 类是处理文件 IO 的主要类, 但是它存在一些缺点.
- 许多方法在失败时并不抛出错误, 所以很难获得一个有效的错误信息, 例如如果一个文件删除失败, 只会返回 false, 而没有任何信息告诉你是因为文件不存在, 还是你没有权限, 又或者是别的问题. 例如以下代码, 删除失败 delete 返回 false, 不抛异常, 不知道具体原因.

        File file = new File("/home/haoyifen/123.txt");
        boolean delete = file.delete();
  • rename 方法在跨平台上表现并不一致
  • 没有真正支持符号链接
  • 需要支持更多的文件元信息 metadata, 例如 file perimissions, file owner 以及一些其他的 security attributes.
  • 获取 metadata 效率不高
  • 很多 File 类的方法并不具有伸缩性, 获取一个含有很多文件的目录的文件列表可能会造成服务器当机, 大的目录可能会造成内存问题
  • 如果存在循环文件链接的话, 无法写出可靠地代码来遍历文件树.

Java7 的 NIO2 中引入 Java.io.file.Path 类来解决 java.io.File 存在的问题

何为 path

现在大多数操作系统以文件树或者层次结构的形式存储文件. 树的顶层是一个或多个 root 节点, 在 root 节点下是文件或者目录, 每一个目录下又可以包含文件和子目录, 子目录又可以包含文件和子目录, 如此循环, 如下图所示.
Java7 NIO2 Path类_第1张图片
Path 就是用来标识文件系统的一个文件. 例如在上图中 statusReport 文件在 Linux 系统下表示为:
/home/sally/statusReport
在 windows 下表示为:
C:\home\sally\statusReport

相对或绝对

Path 分为 relative 和 absolute 两种, 一个 absolute Path 包含 root 节点和完整的目录以定位文件, 例如 /home/sally/statusReport. 而 relative Path 则必须与工作目录接合起来, 才能获取文件. 比如 joe/foo 就是一个 relative Path.

有些系统除了支持典型的文件和目录外, 还支持 Symbolic link(符号链接). 符号链接被用来指向另一个文件, 大多数时候对用户透明, 对符号链接的 read 和 write 操作会指向链接的目标. 但是 delete, rename 操作却只对符号链接起作用, 而不指向目标文件.

例如上面的图中, logfile 对用户来说是个普通的文件, 但是它实际上是指向 dir/logs/HomeLogFile 的符号链接, 对 logFile 的 resolving 会得到 dir/logs/HomeLogFile. 在真实场景中, 大多数系统不限制使用符号链接. 所以会造成循环引用的问题, 也就是说一个链接的目标最终指向了链接本身, 比如 A->B, B->C, C->A. 循环引用会在遍历文件目录时造成无线循环. 当然在 Java 7 的 NIO2 中这个问题已经被考虑和解决了.

Java7 的 Path

在 Java NIO2 中新引进了 Path 类, 是编程上对文件系统路径 (path) 的抽象. Path 对象包含了用来构建路径的文件名和文件目录列表. 这个类作为 Java NIO2 的入口类, 用于替代 Java.io.File 类的操作. Path 实例反映了底层系统, 所以 Path 不是平台无关的, windows 和 linux 下的路径表现方式不同.
Path 对应的文件或目录可以不存在, 你可以创建一个 Path 实例进行很多操作, 添加文件路径, 获取路径的一部分, 或者与另外一个路径进行对比, 同时, 你还可以使用 Files 类来检验该 Path 对应的文件是否存在, 或者创建该文件, open, delete, 改变权限等.

与 java.io.File 的互相转换

Java7 中对 java.io.File 类添加了转换为 Path 的方法

Path path=file.toPath();

同时 Path 类也支持转换为 File 类

File file=path.toFile();

抽象操作

java.nio.file.Path 是对文件路径的一个抽象, 并不需要对应的文件或目录存在, Path 实例的所有操作都是抽象的, 并不与底层文件系统进行操作.
如下所示

//创建一个Path实例
Path path = Paths.get("/home/haoyifen/noneExistFile");
//判断是否是绝对路径
assertEquals(path.isAbsolute(),true);
//从Path中获取信息
assertEquals(path.getFileName().toString(), "noneExistFile");
assertEquals(path.getParent(),Paths.get("/home/haoyifen"));
assertEquals(path.endsWith("noneExistFile"), true);

assertEquals(path.getNameCount(),3);
assertEquals(path.getName(1),Paths.get("haoyifen"));
//解析Path
assertEquals(path.resolve("sub"),Paths.get("/home/haoyifen/noneExistFile/sub"));
assertEquals(path.resolve("/sub"),Paths.get("/sub"));
//获取代表的文件系统
assertEquals(path.getFileSystem(), FileSystems.getDefault());
//转换成File
File file=path.toFile();

Path与File的对应操作

java.io.file.Path类的所有操作都是抽象的, 仅仅只是对抽象路径进行操作, 具体的文件相关操作, 由java.io.file.Files类的静态方法来完成.以下是java.io.File类的方法与java.nio.file.Files类方法的类比关系.
Java7 NIO2 Path类_第2张图片


参考
File I/O (Featuring NIO.2)
Legacy File I/O Code

你可能感兴趣的:(java,Java7,NIO)