Java开发笔记(八十四)文件与目录的管理

程序除了处理内存中的数据结构,还要操作磁盘上的各类文件,这里的磁盘是个统称,泛指可以持久保留数据的存储介质,包括但不限于:插在软驱中的软盘、固定在机箱中的硬盘、插在光驱中的光盘、插在USB接口上的U盘、笔记本电脑里的固态盘、手机中的闪存、相机里的SD卡等等。当然,操作系统层面已经统一了这些存储介质,故而编程语言无须理会它们之间的区别,只需专心访问存储介质上保存的文件。为表述方便,接下来将用“磁盘”二字代指以上罗列的各种存储介质。
Java使用File工具来操作磁盘文件,只要在构造方法中填写某文件的完整路径,即可通过创建好的文件对象进行各项处理。相关的处理方法主要有四大类:检查文件状态、获取文件信息、管理文件操作、遍历某目录下的文件,分别说明如下。

1、检查文件状态
File工具既可操作某个文件,也可操作某个目录。狭义的文件专指一个单独的数据文件,广义的文件则将目录(或称文件夹)也包括在内。下面是检查文件状态的相关方法描述。
exists:判断当前文件/目录是否存在,存在返回true,不存在返回false。
canExecute:判断当前文件是否允许执行,允许返回true,不允许返回false。
canRead:判断当前文件是否允许读取,允许返回true,不允许返回false。
canWrite:判断当前文件是否允许写入,允许返回true,不允许返回false。
isHidden:判断当前文件/目录是否隐藏,隐藏返回true,没隐藏返回false。
isDirectory:判断当前是否为目录,是返回true,否返回false。
isFile:判断当前是否为文件,是返回true,否返回false。

2、获取文件信息
只要磁盘中存在某个文件/目录,就能调用相关方法获取该文件/目录的基本信息,这些方法说明如下:
getAbsolutePath:获取当前文件/目录的绝对路径。
getPath:获取当前文件/目录的相对路径。
getName:如果当前为文件,则返回文件名称;如果当前为目录,则返回目录名称。
getParent:获取当前文件/目录的上级目录路径。
length:如果当前为文件,则返回文件大小;如果当前为空目录,则返回0;如果当前目录非空,则返回该目录的索引空间大小,索引保存了目录内部的文件基本信息。
lastModified:获取当前文件/目录的最后修改时间,单位毫秒。

3、管理文件操作
除了获取文件状态和信息,还能对文件进行创建、删除、更名等管理操作,具体方法列举如下:
mkdir:只创建最后一级目录,如果上级目录不存在就返回false。
mkdirs:创建文件路径中所有不存在的目录。
createNewFile:创建新文件。如果文件路径中的目录不存在,就会扔出异常IOException。
delete:删除文件,也可删除空目录,但不可删除非空目录。在删除非空目录时会返回false。
renameTo:文件重命名,把源文件的名称改为目标名称。

4、遍历某目录下的文件
最后是提供给目录专用的文件遍历操作,主要的遍历方法有list和listFiles两个,其中前者返回的是String类型的文件路径数组,后者返回的是Fille类型的文件路径数组。另外,listFiles方法包括了三个同名的重载方法,它们之间根据参数类型区分开,详细的用法区别见下:
第一个重载的listFiles方法没有输入参数,它返回当前目录下的所有文件和目录。第二个重载的listFiles方法拥有一个FileFilter类型的输入参数,用于根据文件信息筛选符合条件的文件和目录。第三个重载的listFiles方法拥有一个FilenameFilter类型的输入参数,用于根据文件信息和文件名称筛选符合条件的文件和目录。注意FileFilter与FilenameFilter都属于函数式接口,所以它们的实例可以采用Lambda表达式来改写。下面各举一个例子加以说明。
首先利用FileFilter接口查找某个目录下的所有隐藏子目录,常规的过滤代码示例如下:

		File path = new File(mPath); // 创建一个指定路径的文件对象
File[] hiddens;
// 匿名内部类的写法。通过文件过滤器FileFilter来筛选文件
hiddens = path.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isHidden(); // 是隐藏文件
}
});

可见以上的匿名内部类代码明显繁琐,鉴于函数式接口的特性,完全可以将代码使用Lambda表达式精简,简化后的过滤代码只有下面区区一行:

		// Lambda表达式的写法
hiddens = path.listFiles(file -> file.isHidden());

由于上述的Lambda表达式代码符合参数方法引用的规则,因此还能采取方法引用的格式改写如下:

		// 方法引用的写法
hiddens = path.listFiles(File::isHidden);

真是想不到,方法引用的地盘都扩张到文件查找这边了。

再看看FilenameFilter接口,该接口比起FileFilter多了个文件名称,因而经常用于过滤特定扩展名的文件。比如文本文件的扩展名为“.txt”,检查文件是否以“.txt”结尾即可判断它是否为文本文件。仍旧从形态完整的匿名内部类写法着手,此时筛选文本文件的常规代码示例如下:

		File path = new File(mPath);
File[] txts;
// 匿名内部类的写法。通过文件名称过滤器FilenameFilter来筛选文件
txts = path.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".txt"); // 文件扩展名为txt
}
});

同样采取Lambda表达式精简上面的匿名内部类代码,简写后的筛选代码只有以下一行:

		// Lambda表达式的写法
txts = path.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));

更多Java技术文章参见《Java开发笔记(序)章节目录

上一篇:WebService接口定义及调用


下一篇:Linux 账号管理及ACL权限设置,PAM模块简介