1. File类概述
1.1 什么是File类
File是java.io包下作为文件和目录的类。File类定义了一些与平台无关的方法来操作文件,通过调用File类中的方法可以得到文件和目录的描述信息,包括名称、所在路径、读写性和长度等,还可以对文件和目录进行新建、删除及重命名等操作。
对于目录,Java把File类当作一种特殊类型的文件,即文件名单列表。但是File类不能读取文件内容,操作文件内容需要使用输入流和输出流。
1.2 构建 File 对象
File 的构造方法如下:
File(String pathname)
通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。
其中,路径可以是相对路径或者绝对路径。抽象路径应尽量使用相对路径,并且目录的层级分隔符不要直接写”/”或”\”,应使用File.separator 这个常量表示,以避免不同系统带来的差异。代码示意如下所示:
1.3 绝对路径和相对路径
绝对路径是指:无论当前工作目录如何,始终指向文件系统中的相同位置的路径。路径以盘符或/开头。
相对路径是指从某个给定的工作目录开始到目标位置的路径,路径不能以盘符或/开头。
比如查看如下示意:
对于文件 demo.txt,其绝对路径是固定的;但是如果当前工作目录不同,其相对路径的写法也不同。
1.4 使用 File 类示例
首先,创建案例访问的目标文件。在src目录下新建api_03包,在该包下新建一个demo.txt文件,并在该文件中编写任意文字并保存。然后构建 File 对象访问该文件,输出文件的各项信息。
代码示意如下:
package api_03;
import java.io.File;
public class FileDemo1 {
public static void main(String[] args) {
/*
* File创建时需要指定路径
* 路径通常用相对路径,因为绝对路径无法做到
* 平台无关性(window与linux的路径写法不同)
*
* 相对路径中"./"为当前目录,具体是哪里要看
* 当前程序的运行环境而定,在IDEA中运行
* 时,指的就是当前程序所在的项目目录
*/
File file = new File("./src/api_03/demo.txt");
//获取名字
String name = file.getName();
System.out.println(name);
//获取长度(单位是字节)
long length = file.length();
System.out.println(length+"字节");
boolean cr = file.canRead();
boolean cw = file.canWrite();
System.out.println("可读:"+cr);
System.out.println("可写:"+cw);
boolean ih = file.isHidden();
System.out.println("隐藏文件:"+ih);
}
}
2. File类常用操作
2.1 File 操作文件
File的常用方法有:
1、length() 方法
- 返回由此抽象路径名表示的文件的长度(占用的字节量)
- 返回 long 类型的数值
2、exists() 方法
- 测试此抽象路径名表示的文件或目录是否存在
- 返回值:若该File表示的文件或目录存在则返回true,否则返回false
3、createNewFile() 方法
- 当且仅当不存在具有此抽象路径名指定的名称的文件时,创建由此抽象路径名指定的一个新的空文件
- 返回值:如果指定的文件不存在并成功地创建,则返回 true;如果指定的文件已经存在,则返回 false
4、delete() 方法:删除此抽象路径名表示的文件或目录
- 返回值:当且仅当成功删除文件或目录时,返回 true;否则返回 false
- 需要注意的是,若此File对象所表示的是一个目录时,在删除时需要保证此为空目录才可以成功删除(目录中不能含有任何子项)
2.2 创建新文件示例
编写代码,使用File对象创建新文件。代码示意如下:
package api_03;
import java.io.File;
import java.io.IOException;
public class FileDemo2 {
public static void main(String[] args) throws IOException {
/*
* 在当前目录下新建文件:test.txt
*/
File file = new File("./src/api_03/test.txt");
/*
* boolean exists()
* 判断当前File表示的路径下是否已经存在
* 对应的文件或目录
*/
if(!file.exists()) {
file.createNewFile();
System.out.println("文件已创建!");
}else {
System.out.println("文件已存在!");
}
}
}
2.3 删除文件示例
编写代码,使用File对象删除文件。代码示意如下:
package api_03;
import java.io.File;
public class FileDemo3 {
public static void main(String[] args) {
/*
* 将当前目录下的test.txt文件删除
*/
File file = new File("./src/api_03/test.txt");
if(file.exists()) {
file.delete();
System.out.println("文件已删除!");
}else {
System.out.println("文件不存在!");
}
}
}
2.4 File 创建目录
File创建目录时,常用方法有:
1、isDirectory() 方法:判断当前File表示的是否为一个目录,返回 boolean 类型
2、mkdir() 方法:
- 创建此抽象路径名指定的目录
- 当且仅当已创建目录时,返回 true;否则返回 false
3、mkdirs() 方法:
- 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录
- 当且仅当已创建目录以及所有必需的父目录时,返回 true;否则返回 false
- 注意:此操作失败时也可能已经成功地创建了一部分必需的父目录
编写代码,使用File对象创建目录。代码示意如下:
package api_03;
import java.io.File;
public class FileDemo4 {
public static void main(String[] args) {
/*
* 当前目录下新建一个demo目录
*/
File dir = new File("./src/api_03/demo");
if(!dir.exists()) {
dir.mkdir();
System.out.println("目录已创建!");
}else {
System.out.println("目录已存在!");
}
/*
* 当前目录下新建多级目录
* d1/d2/d3
*/
File dir2 = new File("./src/api_03/d1/d2/d3");
if(!dir2.exists()) {
/*
* 该方法会将所有不存在的父目录一同
* 创建出来.而mkdir方法若父目录不存在
* 则创建失败.
*/
dir2.mkdirs();
System.out.println("多级目录已创建!");
}else {
System.out.println("多级目录已存在!");
}
}
}
2.5 File 删除目录
File删除目录时,使用delete() 方法:删除此抽象路径名表示的文件或目录。当且仅当成功删除文件或目录时,返回 true;否则返回 false
需要注意的是,若此File对象所表示的是一个目录时,在删除时需要保证此为空目录才可以成功删除(目录中不能含有任何子项)。
编写代码,使用File对象删除空目录。代码示意如下:
package api_03;
import java.io.File;
public class FileDemo5 {
public static void main(String[] args) {
File dir = new File("./src/api_03/d1/d2/d3");
if(dir.exists()) {
/*
* delete方法删除目录时要求目录
* 必须是空目录,否则不删除
* true-删除成功 false-其他
*/
boolean flag = dir.delete();
if (flag){
System.out.println("目录已删除!");
}else{
System.out.println("删除失败!");
}
}else {
System.out.println("目录不存在!");
}
}
}
2.6 获取目录的所有子项
当目录含有子目录时,可以使用listFiles() 方法:返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的子项(文件或目录)。
返回类型为 File[ ],即抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件和目录。
- 如果目录为空,那么数组也将为空
- 如果抽象路径名不表示一个目录,或者发生 I/O 错误,则返回 null
编写代码,获取当前目录下的所有子项,并打印输出信息。代码示意如下:
public class FileDemo6 {
public static void main(String[] args) {
File dir = new File("./src/api_03");
/*
* boolean isFile()
* 判断当前File表示的是否为文件
*
* boolean isDirectory()
* 判断当前File表示的是否为目录
*/
if(dir.isDirectory()) {
/*
* File[] listFiles()
* 获取当前目录下的所有子项,以一个File数组
* 形式返回,每个元素表示其中一个子项
*/
File[] subs = dir.listFiles();
System.out.println(subs.length);
for(int i=0;i<subs.length;i++) {
System.out.println(subs[i].getName());
}
}
}
}
2.7 求文件夹大小问题
在使用电脑管理文件时,我们经常会查看一个文件夹的大小。文件夹的大小,等于该文件夹各级文件夹中所有文件的大小总和。
假设有文件夹1如下图所示:
此时,文件夹1的总大小为:文件1的大小+文件夹2的大小;文件夹2又等于文件2+文件3;所以总和为 23KB。
这是在确定已知文件夹1只有如图所示的下级内容时。如果不确定文件夹1下有多少级目录,也不确定每个目中有多少个文件,如何来统计呢?
这适用于用递归的思路来解决。
假设有方法 getFile(File file),用于计算文件 file 的大小:
- 如果传入的 file 是文件,则直接获取并返回该文件的大小
- 如果传入的 file 是文件夹,则遍历该文件夹下的每一个子目录,并对每个子目录调用 getFile() 方法,并且把子目录作为参数传入,并对获取到的文件大小求和
逻辑过程如下图所示:
递归的过程如下图所示:
由此可见,使用递归可以解决经典的求文件夹大小的问题。
但是,在使用递归时,必须注意:
1、递归次数尽量少,因为递归的开销较大,效率较差
2、递归操作必须被一个分支语句控制,有条件的执行,否则会出现死循环,并最终造成内存溢出
编写代码,获取文件夹的大小,并打印输出信息。代码示意如下:
package api_03;
import java.io.File;
/**
* 递归示例
* 求api_03文件夹的大小
*/
public class RecursionDemo {
public static void main(String[] args) {
File file = new File("./src/api_03");
long sum = getSize(file);
System.out.println("size = " + sum+" bytes");
}
public static long getSize(File file){
if (file.isFile()){
return file.length();
}else{
File[] files = file.listFiles();
long sum = 0;
for(int i = 0; i < files.length; i++){
sum += getSize(files[i]);
}
return sum;
}
}
}
2.8 FileFilter接口
FileFilter 是用于抽象路径名的过滤器,此接口的实例可传递给 File 类的 listFiles(FileFilter) 方法,用于返回满足该过滤器要求的子项。使用方式如下所示:
File[] listFiles(FileFilter filter)
返回符合要求的 File 对象数组。
编写代码,统计某目录下所有以F开头的文件个数及名称,并打印输出信息。代码示意如下:
package api_03;
import java.io.File;
import java.io.FileFilter;
/**
* 统计api_03目录下所有以F开头的文件个数及名称
*/
public class FileDemo7 {
public static void main(String[] args) {
File dir = new File("./src/api_03");
if(dir.isDirectory()) {
FileFilter filter = new FileFilter() {
public boolean accept(File file) {
String name = file.getName();
System.out.println("正在过滤:"+name);
return name.startsWith("F");
}
};
File[] subs = dir.listFiles(filter);
System.out.println(subs.length);
for(int i=0;i<subs.length;i++) {
System.out.println(subs[i].getName());
}
}
}
}
3. 总结
1、File 是java.io包下作为文件和目录的类
- 通过调用 File 类中的方法可以得到文件和目录的描述信息
- 还可以对文件和目录进行新建、删除及重命名等操作
2、路径
- 绝对路径是指无论当前工作目录如何,始终指向文件系统中的相同位置的路径
- 相对路径是指从某个给定的工作目录开始到目标位置的路径