[疯狂Java]NIO.2:平台无关的文件系统访问支持(Path、Paths、Files)

1. NIO.2简介:

    1) 是Java7新增的功能,是NIO的扩展,主要比原来的NIO多了一些内容,主要有java.nio.file(提供了对文件系统访问的全面支持,并且是平台无关的哟!),还有就是java.nio.channels包下又多了几个Asynchronous开头的Channel接口和类(提供异步非阻塞式Channel,以支持高性能多线程IO);

    2) 小结:NIO.2就是指以上对旧的NIO拓展的两个功能,一个是平台无关的文件系统访问功能,一个是异步非阻塞式Channel;


2. 平台无关的文件系统访问支持:

    1) 原来Java只提供了一个File类来支持对文件系统的访问,但是File有如下诸多缺点:

         i. 平台有关性:Windows的路径分隔符是反斜杠'\',而Unix等系统的路径分隔符是正斜杠'/',这就导致了在不同平台上程序中的路径常量写法不同,最讨厌的是Windows中的反斜杠还需要转义,要用两个反斜杠来表示一个反斜杠!

         ii. 不能利用特定文件系统的特性:为了使File类强行平台无关,就只能用各个OS文件系统的共有的功能,导致很多高级功能不支持(类似于AWT和Swing的关系);

         iii. 大多数File的API在异常时只是返回失败但不会提示具体的异常信息;

    2) NIO.2对文件系统访问的支持:

         i. 主要包含1个接口和2个类,Path接口和Paths/Files工具类;

         ii. Path接口:代表了平台无关的路径,其保存的路径无需使用路径分隔符,只要输入路径的各个节点就可以智能地根据OS来表示出正确的路径;

         iii. Paths/Files工具类:分别包含了大量的静态工具方法来操作路径和文件(就像C语言的库函数一样);

!!Java沿用了一贯的命名风格,例如Arrays工具类就是专门用来操作数据类型数据的,而专门操作集合类型数据的工具类是Collections(即结尾是复数s);


3. Path的简单用法:

    1) 肯定需要先用一个具体的路径来构造一个Path实例咯!但是Path只是一个接口,因此必然会想到用Paths工具类来构造咯!

         i. Path构造方法:static Path Paths.get(String first, String... more);

         ii. 直接用路径节点来构造一个Path,无需输入路径分隔符哦!完美解决了平台依赖的问题哟!例如:Path path = Paths.get("group", "user", "codes");

!!在Windows下表示的路径就是group\user\codes,在Unix等平台上的路径就是group/user/codes了,完美!

    2) 和File类一样,Path中也保存着一个path成员,里面保存着初始化时传入的路径,只不过类型是String[],保存着各个节点的字符串名称;而Path对路径的操作也沿用了File对路径的操作,一切都是基于成员path的字符串操作!!接下来具体讲这些操作都有哪些,而这些方法都是Path的对象方法!!

    3) 获取路径中有几个节点:

         i. 原型:int Path.getNameCount();

         ii. 返回的起始就是String[] path成员的length,在上面的例子中(group-user-codes)结果就是3;

         iii. 注意!包括后面所有的方法都是直接对path的字面值进行解析,并不会深入文件系统,获取该路径所对应的完整的绝对路径或从根结点开始数共有几个节点!!

    4) 获取根结点:

         i. 原型:Path Path.getRoot();

         ii. 根结点在Windows中就是指"x:"类型的结点,比如"c:"、"d:"等,在Unix等系统中就是指根目录"/";

         iii. 使用该方法的前提是成员path的第一个节点必须是上述的根结点,这样返回的新的Path对象中的path成员里就只有一个根结点的字符串,否则该方法只能返回NULL;

!!不要指望该方法会自动深入OS中查找到该路径所对应的完整的绝对路径,然后返回给你一个根结点!错了!它仅仅就是根据path成员的字面值解析而已!!功能上还是比较原始和低级的!

         iv. 例如上述的group-user-codes就只能返回null,但是如果是c:-group-user-codes那就返回c:了;

    5) Path实现了toString方法,因此可以直接使用print等直接打印出其所代表的路径(即path成员),只不过打印出来的内容是带有和平台有关的分隔符的(Win下是\,Uni下是/);

    6) 获取绝对路径(真正深入OS中查询):

        i. 原型:Path Path.toAbsolutePath();

        ii. 如果你初始化时的path路径里已经包含根结点了,那它返回的还是原来的路径,因为包含根结点的路径就是绝对路径!

        iii. 如果你初始化是的path是相对路径,那么它就将当前Java程序的路径作为上级路径合成一个绝对路径,例如初始时输入的路径是还是上面的例子,而当前Java程序的路径d:\codes\Test\,那么将返回d:\codes\Test\group\user\codes了;


4. Files工具类——全面使用OS文件系统:接下来介绍的全部都是Files类的静态工具方法,这里只介绍几个常用的工具方法

    1) long copy(Path source, OutputStream out);  // 从source拷贝到out

    2) List<String> readAllLines(Path path[, Charset cs]);  // 读取path指定的文件的所有行保存到String列表中返回,可以选择性指定编码

    3) Path write(Path path, Iterable<? extends CharSequence> lines[, Charset cs], OpenOption... options); // 将字符串序列写入写入path指定的文件中

!!options暂时不管,一般用不到;

!!可以选择性指定编码表;

!!lines其实就是可迭代的字符串序列,比如List<String>、String[]什么都可以,只要是可迭代的就行;

    4) boolean isHidden(Path path);  // 判断path所指定的文件是否为隐藏文件

    5) long size(Path path); // 返回指定文件的大小(字节)


5. Java8新加入Files的功能——Stream API:同样都是Files工具类的静态工具方法

    1) 列出当前目录下所有的文件和子目录:

         i. 原型:Stream<Path> list(Path dir);

         ii. 返回的是Path的Stream列表,而Stream<Path>用其forEach方法遍历;

         iii. void forEach(Consumer<? super T> action);

         iv. 而action是一个函数式接口,里面只有一个接口方法:void accept(T t);,而在这里,T就是dir下的每个文件了(类型是Path);

         v. 因此可以这样用:Files.list(".").forEach(path -> System.out.println(path)); // 打印当前目录下的每个子目录和文件的路径名

    2) 列出文件中的每行:

         i. Stream<String> lines(Path path[, Charset cs]);

         ii. 同样可以使用Stream列表的forEach方法遍历,只不过参数变成了Stream里面的Path对象了,表示罗列出的每一行;

         iii. 示例:Files.lines(Paths.get("."), Charset.forName("gbk")).forEach(line -> System.out.println(line));

    3) 获得驱动盘的存储空间信息:

         i. 首先通过Files的getFileStore工具方法获取驱动盘的存储空间句柄:static FileStore Files.getFileStore(Path path);

!!FileStore就是驱动器盘存储空间信息句柄(对象),它代表了path所在的驱动盘的存储空间信息;

         ii. 接着调用FileStore的getTotalSpace和getUsableSpace来查询驱动盘的总空间和可用空间:

             a. long FileStore.getTotalSpace(); // 返回FileStore所代表的驱动盘的总空间,单位是字节

             b. long FilesStore.getUsableSpace(); // 返回FileStore所代表的驱动盘的剩余可用空间,单位是字节

!!注意:

        a. 在使用getFileStore时path只需要指定根结点就行(盘符),例如"c:"、"d:"等;

        b. 因为FileStore只能代表驱动盘,而驱动盘只需要用盘符来确定就行了,最终getTotalSpace等得到的结果也是整个驱动盘的;

        c. 如果path指定的是一个完整的路径名(例如“c:\intel"),那它最终还是会转化成"c:"这一个根结点,最终不会计算intel这个目录的存储空间,因为存储空间这个概念只适用于整个驱动盘;

        d. 如果你path指定的是一个相对路径(路径中不包含根结点),那么它会将当前Java程序所在的驱动盘作为最终结果返回!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值