Java开发笔记(九十五)NIO配套的文件工具Files
NIO不但引进了高效的文件通道,而且新增了更加好用的文件工具家族,包括路径组工具Paths、路径工具Path、文件组工具Files。先看路径组工具Paths,该工具提供了静态方法get,输入某个文件的路径字符串,输出该文件路径的路径对象Path。通过get方法获取路径对象的代码示例如下:
// 根据指定的文件路径字符串获得对应的Path对象
Path path = Paths.get(mDirName);
有了Path对象之后,就能调用它的各种实例方法了,常见的几个方法说明如下:
getParent:获取当前路径所在的上级目录的Path对象。
resolve:拼接文件路径,在当前路径的末尾添加指定字符串,并返回新的文件路径。
startsWith:判断当前路径是否以指定字符串开头。
endsWith:判断当前路径是否以指定字符串结尾。
toString:获取当前路径对应的名称字符串。
toFile:获取当前路径对应的File对象。
看上去路径组工具Paths和路径工具Path平淡无奇,并无什么出众之处。原来真正方便的是文件组工具Files,它集成了众多实用的功能技巧,且看下列的各个方法说明:
exists:判断该路径是否存在。
isDirectory:判断该路径是否为目录。
isExecutable:判断该路径是否允许执行。
isHidden:判断该路径是否隐藏。
isReadable:判断该路径是否可读。
isWritable:判断该路径是否可写。
size:获取该路径的文件大小。如果该路径是文件,则返回文件大小;如果该路径是目录,则返回目录基本信息的大小,而非整个目录的大小。
createDirectory:如果该路径是个目录,就创建新目录。
createFile:如果该路径是个文件,就创建新文件。
delete:如果该路径是文件或者空目录,就把它删掉。如果该路径不存在或者目录非空,就扔出异常。
deleteIfExists:如果该路径是文件或者空目录,就把它删掉(路径不存在也不报错)。但若目录非空,还是扔出异常。
copy:把文件从源路径复制到目标路径。
move:把文件从源路径移动到目标路径。
另外,Java8又给Files工具增加了以下几个方法,使之具备流式处理的能力:
readAllLines:获取该文件的所有内容行,返回的是字符串清单。
lines:获取该文件的所有内容行,返回的是字符串流Stream<String>。
list:获取该目录下的所有文件与目录,但不包括子目录的下级内容,返回的是路径流Stream<Path>。
walk:获取该目录下的所有文件与目录,且包括指定深度子目录的下级内容,返回的是路径流Stream<Path>。
接下来通过几个实际案例演示以上文件工具的详细用法。
一、通过Path打开文件通道
之前介绍文件通道的时候,提到有两种方式可以创建文件通道,第一种方式可以调用输入输出流的getChannel方法获取通道对象,第二种方式可以调用随机文件工具的getChannel方法获取通道对象。其实还有第三种方式,就是调用FileChannel工具的open方法,根据传入的Path对象也能获得通道对象。不加选项参数的open方法,默认得到只读的文件通道;若要得到可写的文件通道,则需给open方法传入选项参数StandardOpenOption.WRITE。下面是利用路径工具创建文件通道的代码例子:
// 通过Path打开文件通道
private static void openChannelFromPath() {
try {
// 根据指定的文件路径字符串获得对应的Path对象
Path path = Paths.get(mFileName);
// 创建文件通道的第三种方式:通过Path打开文件的只读通道。open方法不加选项参数的话,默认是只读权限
FileChannel readChannel = FileChannel.open(path, StandardOpenOption.READ);
readChannel.close();
// 创建文件通道的第三种方式:通过Path打开文件的写入通道。
// open方法的第二个参数指定了文件以只读方式还是以可写方式打开
FileChannel writeChannel = FileChannel.open(path, StandardOpenOption.WRITE);
writeChannel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
需要注意的是,通过Path打开可写的文件通道有个问题:要是文件通道指向的文件路径并不存在,那么往该通道写入数据将会扔出异常,而非默认创建新文件。因而获取可写的文件通道之前必须添加检查代码,即判断指定路径是否存在,倘若该路径不存在,则要创建一个新文件。完整的检查代码如下所示:
// 根据文件路径获取Path对象。如果指定路径的文件不存在,就创建一个新文件。
private static Path getPath(String filename) {
Path path = Paths.get(filename);
if (!Files.exists(path)) { // 该文件路径并不存在
try {
Files.createFile(path); // 在该路径创建新文件
} catch (IOException e) {
e.printStackTrace();
}
}
return path;
}
可是依稀记得,不管是从输入输出流获取文件通道,还是从随机文件工具获取文件通道,都没有手工创建新文件的步骤呀。那是因为即使指定路径的文件不存在,输出流和随机文件工具都会自动创建文件,无需程序员去手工创建。因此实际开发中若要创建文件通道,基本采取前两种方式,很少使用Path工具的第三种方式。
二、遍历指定目录下(不包含子目录)的所有文件与目录
调用Files工具的list方法即可实现指定目录(不包含子目录)的遍历功能,list方法返回的遍历结果为字符串流,后续即可通过流式处理做进一步的加工。比如要统计指定目录下面文件与目录数量,则先调用list方法获得字符串流对象,再调用count方法就能得到统计数目。具体的统计代码示例如下:
// 根据指定的文件路径字符串获得对应的Path对象
Path path = Paths.get(mDirName);
try {
// 计算该目录下(不包含子目录)的所有文件与目录的总数
long listCount = Files.list(path).count();
System.out.println("listCount="+listCount);
} catch (Exception e) {
e.printStackTrace();
}
三、遍历指定目录下(包含子目录)的所有文件与目录
倘若要求对指定目录及其子目录进行遍历操作,则可调用Files工具的walk方法,该方法支持设定待遍历的子目录深度(从当前目录往下数的目录层数)。譬如要统计指定目录及五层以内子目录下面文件与目录数量,则先调用walk方法获得字符串流对象,再调用count方法就能得到统计数目。此时包含子目录的统计代码如下所示:
try {
// 根据指定的文件路径字符串获得对应的Path对象
Path path = Paths.get(mDirName);
// 遍历该目录以及深度在五之内的子目录,计算其下所有文件与目录的总数
long count = Files.walk(path, 5).count();
System.out.println("count="+count);
} catch (Exception e) {
e.printStackTrace();
}
walk方法与list方法同样返回的都是流对象,所以流式处理的filter、map、collect等方法统统适用,非常方便对某目录下的所有实体进行筛选操作。例如打算遍历指定目录以及深度在五之内的子目录,并返回其下所有目录的路径名称清单,利用walk方法实现的筛选代码是下面这样的:
try {
// 根据指定的文件路径字符串获得对应的Path对象
Path path = Paths.get(mDirName);
// 遍历该目录以及深度在五之内的子目录,并返回其下所有目录的路径名称清单
List<String> dirs = Files.walk(path, 5)
.filter(Files::isDirectory) // 只挑选目录
.map(it -> it.toString()) // 获取目录的路径名称
.collect(Collectors.toList()); // 返回清单格式
System.out.println("dirs="+dirs);
} catch (Exception e) {
e.printStackTrace();
}
由此可见,流式处理在NIO的文件工具中大放异彩,代码逻辑结构清晰、代码行数量也少,实为文件遍历的一员福将。
通过walk方法筛选指定目录下的某种类型文件也很方便,例如想要挑出某目录下面所有的png图片文件路径,则采取walk方法辅以流式处理的实现代码如下所示:
try {
// 根据指定的文件路径字符串获得对应的Path对象
Path path = Paths.get(mDirName);
// 遍历该目录以及深度在五之内的子目录,并返回其下所有png文件的路径名称清单
List<String> pngs = Files.walk(path, 5)
.filter(it -> it.toFile().isFile()) // 只挑选文件
.filter(it -> it.endsWith(".png")) // 挑出扩展名为png的文件
.map(it -> it.toString()) // 获取目录的路径名称
.collect(Collectors.toList()); // 返回清单格式
System.out.println("pngs="+pngs);
} catch (Exception e) {
e.printStackTrace();
}
以上的文件筛选代码果然清爽,一点都不拖泥带水。
更多Java技术文章参见《Java开发笔记(序)章节目录》
Java开发笔记(九十五)NIO配套的文件工具Files的更多相关文章
- Java开发笔记(五十)几种开放性修饰符
前面介绍子类继承父类的时候,提到了public(公共)和private(私有)两个修饰符,其中public表示它所修饰的实体是允许外部访问的:而private表示它所修饰的实体不允许外部访问,只能在当 ...
- Java开发笔记(五十一)多态的发生场景
江湖上传闻,面向对象之所以厉害,是因为它拥有封装.继承与多态三项神技,只要三板斧一出,号令天下谁敢不从.前面费了老大的劲才讲清楚封装和继承,那么多态又是怎样的神乎其神呢?下面先通过一个简单的例子来说明 ...
- Java开发笔记(五十二)对象的类型检查
前面介绍了类的多态性,来自于鸡类的实例chicken,既能用来表达公鸡实例,也能用来表达母鸡实例.可是这导致了一个问题,假如在call方法内部需要手工判断输入参数属于公鸡实例还是母鸡实例,那该如何是好 ...
- Java开发笔记(五十三)关键字final的用法
前面介绍了多态的相关用法,可以看到一个子类从父类继承之后,便能假借父类的名义到处晃悠.这种机制在正常情况之下没啥问题,但有时为了预防意外发生,往往只接受当事人来处理,不希望它的儿子乃至孙子来瞎掺和.可 ...
- Java开发笔记(五十四)内部类和嵌套类
通常情况下,一个Java代码文件只定义一个类,即使两个类是父类与子类的关系,也要把它们拆成两个代码文件分别定义.可是有些事物相互之间密切联系,又不同于父子类的继承关系,比如一棵树会开很多花朵,这些花儿 ...
- Java开发笔记(五十五)关键字static的用法
前面介绍嵌套类的时候讲到了关键字static,用static修饰类,该类就变成了嵌套类.从嵌套类的用法可知,其它地方访问嵌套类之时,无需动态创建外层类的实例,直接创建嵌套类的实例就行.其实static ...
- Java开发笔记(五十六)利用枚举类型实现高级常量
前面介绍了联合利用final和static可实现常量的定义,该方式用于简单的常量倒还凑合,要是用于复杂的.安全性高的常量,那就力不从心了.例如以下几种情况,final结合static的方式便缺乏应对之 ...
- Java开发笔记(五十七)因抽象方法而产生的抽象类
前面介绍了类的常见用法,令人感叹面向对象的强大,几乎日常生活中的所有事物,都可以抽象成Java的基类及其子类.然而抽象操作也有副作用,就是某个抽象而来的行为可能是不确定的,比如半夜鸡叫,如果是公鸡则必 ...
- Java开发笔记(五十八)简单接口及其实现
前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...
随机推荐
- VS1053 datasheet 解读笔记
pdf 10 pdf 11 ` 左右声道 负载,注意这里的负载指LEFT 到GBUF,RIGHT到GBUF.所以后面会有说明GBUF一定不能连接到GND. pdf 14 pdf 14 从上面的引脚定 ...
- ios 短音效的使用
1.通用短音效ID的获取 #import <Foundation/Foundation.h> @interface MJAudioTool : NSObject /** * 播放音效 * ...
- 利用WebViewJavascriptBridge与UIWebView进行交互
事情的起因还是因为项目需求驱动.折腾了两天,由于之前没有UIWebView与JS交互的经历,并且觉得这次在功能上有一定的创造性,特此留下一点文字,方便日后回顾. 我要实现这样一个需求:按照本地的CSS ...
- HDU 3714/UVA1476 Error Curves
Error Curves Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- 初探linux子系统集之led子系统(二)【转】
本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37606487 巴西世界杯,德国7比1东道主,那个惨不忍睹啊,早上起来看新闻,第一 ...
- UVA11613 Acme Corporation —— 最小费用流(流量不固定的最小费用流)
题目链接:https://vjudge.net/problem/UVA-11613 题意: 商品X在第i个月内:生产一件需要花费mi元,最多可生产ni件,销售一件(在这个月内销售,而不管它是在那个月生 ...
- 请问snmp到底是干啥的。
这个事情分两方面来说:首先是路由器这部分.路由器开启SNMP功能之后,它能够对自己的每个接口上的流量有一个统计,当然统计的不单单只有流量.然后路由器把统计到的内容按一定的格式保存起来.这个格式是大家都 ...
- 【扬中集训DAY2T2】 机智的AmyZhi
[题目链接] 点击打开链接 [算法] 据说标算是暴力? 从N-200开始搜 不过我用了搜索+一些奇怪的剪枝,也A了.... [代码] 标程 #include<bits/stdc++.h> ...
- phpstorm 10 初体验
一:安装phpstorm 10 去phpstorm 10官网下载,安装 https://www.jetbrains.com/phpstorm/ 按照提示安装,最后注册步骤,选择“License ser ...
- JAVA Synchronized (三) volatile 与 synchronized 的比较
一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...