[01] File类
1、IO概念
File类是java.io包中一个很重要的类,这里的io,就是指 Input/Output,所以在看File类之前,先提一下所谓的IO概念。
I/O(Input/Output),即输入/输出,通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出:
- 如从键盘上读取数据,从本地或网络上的文件读取数据或写入数据
- 通过输入和输出操作可以从外界接收信息,或者把信息传递给外界
这里的输入还是输出,是针对内存来说的:
- 把数据读入到内存中,为输入Input,进行数据的read操作
- 把内存往外部设备写数据,称为输出Output,进行数据的write操作
在Java中,是把输入和输出操作用“流”来实现的,通过统一的接口来表示,这个在后面会讲到。
2、File类
程序中不可避免地会使用到IO方面的操作,Java中的java.io包中就是针对IO操作的类和接口,而File类则是之中很重要的一个类。
File类的对象可以表示(封装)一个文件,或者是目录。该对象可以对其表示的文件或目录的属性进行操作,如文件名修改,最后修改日期等等。
File对象无法操作文件的具体数据,即不能直接对文件进行读/写操作。
2.1 File类的构造方法
File类的构造方法有几种重载方式:
- public File(String pathname) 根据路径得到File对象
- File file = new File("C:\\demo\\a.txt");
- public File(String parent, String child) 根据一个目录和一个子文件/目录得到File对象
- File file = new File("C:\\demo", "a.txt");
- public File(File parent, String child) 根据一个父File对象和一个子文件/目录得到File对象
- File baseFile = new File("C:\\demo"); File file = new File(baseFile, "a.txt");
路径的分隔符,要么使用 "/",要么使用 "\\",甚至可以用 File.Separater 来替代,如 File file = new File("c" + File.Separater + "test.txt");
以上三种方式的最终效果都是一样的,最常用的还是File(String pathname),指定路径创建文件对象。
要说明的是,这里只是创建一个跟指定文件关联的File对象,而不是创建了一个文件或目录。
2.2 File类的常用方法
返回值 | 方法名 | 说明 |
boolean | exists() | 判断文件是否存在 |
boolean | isFile() | 判断是否为文件 |
boolean | isDirectory() | 判断是否为目录 |
String | getName() | 获取文件的名称 |
String | getAbsolutePath() | 获取文件的绝对路径 |
long | length() | 获取文件的大小长度(字节数) |
boolean | createNewFile() | 创建新文件,返回执行结果 |
boolean | delete() | 删除文件,返回执行结果 |
boolean | canWrite() | 是否可写 |
2.3 创建File
new获得到File对象,只是关联了文件的一个对象,而我们真正想要实现创建文件或目录的话,则要调用相应的方法。
2.3.1 创建目录
返回值 | 方法名 | 说明 |
boolean | mkdir() | 根据File对象创建一个目录 |
boolean | mkdirs() | 根据File对象创建整个目录 |
mkdir()和mkdirs()的区别在于,假如有 File file = new File("D:/abc/xyz/hello");
- mkdir()创建目录,必须上一级目录存在。如例若D盘下abc目录存在,但xyz目录不存在,则不能成功创建hello目录
- mkdirs()创建File对象包含的整个目录,不论路径中某个目录实际是否存在,不存在则创建
注意和创建文件区别,假如有 File file = new File("C:/test/test.txt"); 如果使用的是mkdirs(),则最终会创建一个名为 "test.txt" 的文件夹,而不是创建出 test.txt 的文本文件
2.3.2 创建文件 (New / Temp)
返回值 | 方法名 | 说明 |
boolean | createNewFile() | 创建新的文件 |
boolean | File.createTempFile() | 创建新的临时文件 |
- createNewFile() 根据路径创建空文件,当路径不存在,或文件已存在则创建失败(这意味着最好先调用exists方法判断)
- File.createTempFile() 根据路径创建临时文件,可指定文件名前后缀以及文件目录,若不指定目录则放在系统临时文件夹下
后者 File.createTempFile() 创建临时文件,是File类的一个静态方法,同样,该方法也要求首先路径存在,不会自动创建目录。其方法有两种重载方式:
- createTempFile(String prefix, String suffix)
- createTempFile(String prefix, String suffix, File directory)
其中prefix是文件名的前缀;suffix是文件的后缀,如果suffix不是“点和文件类型”的形式,例如 ".txt",则suffix作为文件名末尾,否则作为文件类型:
之前对createTempFile()的用途不是很理解,以为该文件在创建完一定时间后会自动清理,所以称之为临时文件,实际上不是的。存在还是会一直存在,其临时文件的主要含义在于其文件名,上图例中可以看到,文件名是自定义的前后缀加中间的一串数字,构成了一个文件名唯一的文件。
也即是说,File.createTempFile 的用途是当你想要建立一个文件暂时使用,但是你不在乎其精确的文件名,只要不覆盖已存在的文件时即可。你可以指定临时文件的前缀(不得太短,不得为null),以及文件的后缀(可以为null,则默认后缀为 .tmp)和文件所在目录,如果不指定目录,则存放在系统的临时文件夹下。
2.4 删除文件 (delete / deleteOnExit)
删除文件的方法为 delete(),返回值类型为boolean,该删除文件不会放入回收站中,而是直接删除。
File file = new File("C:/test/test.txt");
if(file.exists()){
file.delete();
}
4
1
File file = new File("C:/test/test.txt");
2
if(file.exists()){
3
file.delete();
4
}
还有一个方法很类似,叫做 deleteOnExit(),注意不是 deleteOnExists(),所以这个方法并不是所谓的判断文件如果存在再删除。那么什么叫做退出时删除呢?
deleteOnExit 的解释为,当虚拟机终止时,请求删除此抽象路径名表示的文件或目录。也就是说,deleteOnExit成功运行后,文件并没有直接删除,而是在虚拟机运行结束后才会删除。
这个方法实际上和上面提到的 createTempFile 是对应的,也即使说,这个方法通常是用在临时文件的删除。场景如:程序有个需求需要创建临时文件,这个临时文件可能作为存储使用,但是程序运行结束后,这个文件应该就被删除了。在哪里做删除操作呢,需要监控程序关闭吗?如果很多东西可以终止程序,那么这个删除操作需要都放置一份吗?其实就这么写,程序结束后文件就会被自动删除了:
File file = File.createTempFile("tmp", null);
file.deleteOnExit();
2
1
File file = File.createTempFile("tmp", null);
2
file.deleteOnExit();
也可以这样写,然后在最后的println处打断点进行测试:
public static void main(String[] args) throws IOException {
File directory = new File("C:/test");
File temp = File.createTempFile("temp", null, directory);
temp.deleteOnExit();
System.out.println("deleteOnExit()已经执行!");
System.out.println("real end"); //此处打断点暂停,发现文件尚未删除
}
9
1
public static void main(String[] args) throws IOException {
2
File directory = new File("C:/test");
3
File temp = File.createTempFile("temp", null, directory);
4
5
temp.deleteOnExit();
6
7
System.out.println("deleteOnExit()已经执行!");
8
System.out.println("real end"); //此处打断点暂停,发现文件尚未删除
9
}
3、File类的遍历
3.1 遍历
File类中有 list() 和 listFiles() 方法
返回值 | 方法名 | 说明 |
String[] | list() | 将目录下的子目录及文件的名字,返回到String数组中 |
File[] | listFiles() | 将目录下的子目录及文件的实例返回到File数组中 |
注:这里返回的文件名称包含文件类型的后缀
3.2 过滤
为了根据某些条件获取我们想要的结果集,Java提供了两个过滤器接口,作用如其名:FilenameFilter 和 FileFilter
然后我们就可以使用重载的list方法,以过滤器作为参数传入来进行结果过滤:
- list ( FilenameFilter filter )
- listFiles ( FileFilter filter )
- listFiles ( FilenameFilter filter )
当然,这两个接口的实现类,要求实现accept方法,以自定义过滤规则,符合条件规则的返回true:
- FilenameFilter 要求实现 boolean accept ( File dir, String name )
- dir:表示文件的当前目录
- name:表示当前目录的子目录或文件的名字
- FileFilter 要求实现 boolean accept ( File pathName)
- pathName:表示当前目录的子目录或文件的名字
如筛选 .java 类型的文件:
public class MyFilenameFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
if (name.endsWith(".java")) {
return true;
} else {
return false;
}
}
}
10
1
public class MyFilenameFilter implements FilenameFilter {
2
3
public boolean accept(File dir, String name) {
4
if (name.endsWith(".java")) {
5
return true;
6
} else {
7
return false;
8
}
9
}
10
}
public static void main(String[] args) throws IOException {
File directory = new File("C:/test");
String[] dirs = directory.list(new MyFilenameFilter());
for (String dir : dirs) {
System.out.println(dir);
}
}
8
1
public static void main(String[] args) throws IOException {
2
File directory = new File("C:/test");
3
4
String[] dirs = directory.list(new MyFilenameFilter());
5
for (String dir : dirs) {
6
System.out.println(dir);
7
}
8
}
如筛选文件类型的File对象,去掉目录类型:
public class MyFileFilter implements FileFilter{
public boolean accept(File pathname) {
if (pathname.isFile()) {
return true;
} else {
return false;
}
}
}
10
1
public class MyFileFilter implements FileFilter{
2
3
public boolean accept(File pathname) {
4
if (pathname.isFile()) {
5
return true;
6
} else {
7
return false;
8
}
9
}
10
}
public static void main(String[] args) throws IOException {
File directory = new File("C:/test");
File[] files = directory.listFiles(new MyFileFilter());
for (File file : files) {
System.out.println(file.getName());
}
}
x
1
public static void main(String[] args) throws IOException {
2
File directory = new File("C:/test");
3
4
File[] files = directory.listFiles(new MyFileFilter());
5
for (File file : files) {
6
System.out.println(file.getName());
7
}
8
}
4、总结
- File对象封装了一个文件/目录,不能操作文件内容
- 通过File对象可以创建或删除文件/目录,留意createTempFile和deleteOnExit
- File对象的遍历可以通过过滤器进行筛选
5、其他知识点延伸
5.1 FileCopyUtils.copy()
org.springframework.util 包中有个FileCopyUtils类(更多参考API),该类提供了许多一步式的静态操作方法,能够将文件内容拷贝到另一个目标,这个目标可以是byte[],String,甚至一个输出流或者另外输出到一个文件中。
这里主要叙述一下文件内容的拷贝方法说明,更多的也可以参考链接《Spring优秀工具类Resource》