NIO不但引进了高效的文件通道,并且新增了更加好用的文件工具家族,包括路径组工具Paths、路径工具Path、文件组工具Files。先看路径组工具Paths,该工具提供了静态方法get,输入某个文件的路径字符串,输出该文件路径的路径对象Path。经过get方法获取路径对象的代码示例以下:html
// 根据指定的文件路径字符串得到对应的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>。程序员
接下来经过几个实际案例演示以上文件工具的详细用法。工具
1、经过Path打开文件通道
以前介绍文件通道的时候,提到有两种方式能够建立文件通道,第一种方式能够调用输入输出流的getChannel方法获取通道对象,第二种方式能够调用随机文件工具的getChannel方法获取通道对象。其实还有第三种方式,就是调用FileChannel工具的open方法,根据传入的Path对象也能得到通道对象。不加选项参数的open方法,默认获得只读的文件通道;若要获得可写的文件通道,则需给open方法传入选项参数StandardOpenOption.WRITE。下面是利用路径工具建立文件通道的代码例子:spa
// 经过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打开可写的文件通道有个问题:要是文件通道指向的文件路径并不存在,那么往该通道写入数据将会扔出异常,而非默认建立新文件。于是获取可写的文件通道以前必须添加检查代码,即判断指定路径是否存在,假若该路径不存在,则要建立一个新文件。完整的检查代码以下所示:htm
// 根据文件路径获取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工具的第三种方式。对象
2、遍历指定目录下(不包含子目录)的全部文件与目录
调用Files工具的list方法便可实现指定目录(不包含子目录)的遍历功能,list方法返回的遍历结果为字符串流,后续便可经过流式处理作进一步的加工。好比要统计指定目录下面文件与目录数量,则先调用list方法得到字符串流对象,再调用count方法就能获得统计数目。具体的统计代码示例以下:blog
// 根据指定的文件路径字符串得到对应的Path对象 Path path = Paths.get(mDirName); try { // 计算该目录下(不包含子目录)的全部文件与目录的总数 long listCount = Files.list(path).count(); System.out.println("listCount="+listCount); } catch (Exception e) { e.printStackTrace(); }
3、遍历指定目录下(包含子目录)的全部文件与目录
假若要求对指定目录及其子目录进行遍历操做,则可调用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开发笔记(序)章节目录》