File类
构造方法
作为IO操作中的最基本的类,File类可以封装文件夹和文件,其构造方法如下:
1、通过给定的父抽象路径名和子路径名字符串创建一个新的File实例。
File(File parent, String child);
2、通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。
File(String pathname)
3、根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(String parent, String child)
4、通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例。
File(URI uri)
下面是对构造方法的演示:
public static void main(String[] args)
{
/**
File类的构造函数
如何创建文件对象
**/
String pathname = "D:\forio";
String pathname2 = "D:\forio\3.txt"; //封装的是3.txt这个文件
File f1 = new File(pathname); //将forio文件夹封装成对象,注意也可以封装不存在的文件或者文件夹,变成对象,可以再创建嘛
System.out.println(f1);
File f2 = new File("D:\forio","3.txt");//分开之后可以将后面的变成一个变量
System.out.println(f2);
File dir = new File("D:\forio");
File f3 = new File(dir,"3.txt");
System.out.println(f3);
//也可以像下面这样,File.separator表示系统分隔符,可以适应所有系统,不止Windows
File f4 = new File("D:"+File.separator+"forio"+File.separator+"3.txt");
System.out.println(f4);
}
操作文件的方法
成功创建对象后就可以调用类的方法来操作文件或文件夹,这些方法比较多,就不罗列了,可以去文档查,下面介绍几个比较常用的方法。
1、获取基本信息
public static void main(String[] args)
{
/*
File类的方法演示
获取文件的信息,名称,大小,时间
*/
File file = new File("D://forio//3.txt");
String absPath = file.getAbsolutePath(); //绝对路径
String pathString= file.getPath(); //File中封装的路径是什么获取的就是什么
String filename = file.getName();
long size = file.length(); //字节数
long time = file.lastModified(); //毫秒值
System.out.println("absPath="+absPath);
System.out.println("Path="+pathString);
System.out.println("filename="+filename);
System.out.println("size="+size);
System.out.println("time="+time);
//毫秒值--Date--格式化--字符串文本
String str_date = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG).format(new Date(time));
System.out.println(str_date);
}
2、创建、删除、存在
对文件夹和文件还有创建和删除操作,以及判断目录是否存在。
对文件夹的: File dir = new File("D:\demo");
File dirs = new File("D:\haha\hehe\xixi");
- 创建单层文件夹:dir.mkdir();
- 创建多层文件夹:dirs.mkdirs();
- 删除文件夹:dir.delete(); dirs.delete();如果文件夹中有内容,需要先删除其中内容,再对文件夹进行删除
- 判断是否存在: dir.exists();
对文件的: File file = new File("D:\forio\3.txt");
- 创建文件:file.createNewFile();
- 删除文件:file.delete();
- 判断存在:file.exists();
以上方法的返回值都是boolean类型,成功或存在返回True,否则返回False
- 创建文件,如果文件不存在,创建,返回true
- 如果存在,不创建,返回false
- 如果路径错误,IOException
- 删除时返回false的两种情况:1、不存在,2、正在使用
3、ListFile方法,列举目录下的全部内容
ListFile方法返回值是一个File对象的数组,存放着目录中所有文件以及文件夹对象
import java.io.File;
public class ListFiles {
public static void main(String[] args)
{
//需求:对给定的目录获取内部的内容
File dir = new File("D:\forio");
//判断:1、必须是存在的 2、必须是目录,否则容易引发空指针异常NullPointerException
String[] names = dir.list(); //获取的是目录下的当前的文件以及文件夹名称
for (String name : names) {
// System.out.println(name);
}
File[]files = dir.listFiles(); //获取目录下的当前文件以及文件夹对象
for (File file : files) {
System.out.println(file.getName());
}
}
}
4、过滤器
过滤文件名的过滤器,实现FilenameFilter接口,并重写accept方法,如果文件名按照预先设定的规则,就返回True,否则返回False
public class FilenameFilterByTxt implements FilenameFilter {
private String suffix;
//构造函数
public FilenameFilterByTxt(String s){
suffix = s;
}
//重写accept函数
@Override
public boolean accept(File file, String name) {
return name.endsWith(suffix); //也可以直接endwith(".txt"); 但这样可以减少耦合性,更灵活的选择以哪种结束
}
}
public class FileDemo {
public static void main(String[] args)
{
//需求:获取目录中的文件,只要.txt文件
File dir = new File("D:\forio");
File[] files = dir.listFiles(new FilenameFilterByTxt(".txt")); //传入过滤器,如果懵逼了可以查看listFiles的API
/* listFiles方法的源码:
*
* public File[] listFiles(FilenameFilter filter)
* {
String ss[] = list(); //调用File类中的list方法,先获取所有的名称
if (ss == null) return null; //判断,如果数组为空,返回
ArrayList<File> files = new ArrayList<>(); //创建了一个集合,元素是File类型
for (String s : ss) //遍历数组名称
//调用accept方法,对遍历的名称进行过滤器判断,将当前目录this,遍历到名称s传递给accept方法,如果过滤器为空,即没有过滤条件。则全部为真
if ((filter == null) || filter.accept(this, s))
files.add(new File(s, this)); //将满足过滤条件的添加到集合中,将名称和当前目录封装成File对象。new File(dir,name);
return files.toArray(new File[files.size()]); //将集合转成数组返回,因为不需要增删操作
}
* */
for (File file : files) {
System.out.println(file);
}
}
}
过滤文件夹的过滤器,和上面迭代器的不同,少了一个私有成员,accept函数也少了一个参数,实际上是对accept函数的重载
public class FileFilterByDir implements FileFilter {
@Override
public boolean accept(File pathname) {
// TODO Auto-generated method stub
return pathname.isDirectory();
}
}
import java.io.File;
import java.io.FileFilter;
public class Demo
{
public static void main(String[] args)
{
File dir = new File("D:\forio");
/*
public File[] listFiles(FileFilter filter) {
String[] ss = this.list();
if (ss == null) {
return null;
} else {
ArrayList<File> files = new ArrayList();
String[] var4 = ss;
int var5 = ss.length;
for(int var6 = 0; var6 < var5; ++var6) {
String s = var4[var6];
File f = new File(s, this);
if (filter == null || filter.accept(f)) {
files.add(f);
}
}
*/
File[] files = dir.listFiles(new FileFilterByDir());//传入过滤器,如果懵逼了可以查看listFiles的API
for (File file : files) {
System.out.println(file);
}
}
}
练习
1、获取目录中的所有内容,因为一个文件夹内可能包含文件也可能还包含文件夹,所以需要使用递归,用一个全局变量统计数目。
public class exercise1 {
static int acount=0; //统计数目
public static void main(String[] args)
{
/***
* File类的listFiles()列出当前目录下的文件以及文件夹内容
*
* 需求:能不能列出当前目录下的子目录中的所有内容
* 思路:
* 1、在遍历当前目录时,会获取到当前的所有文件及文件夹
* 2、要遍历子目录需要对获取的当前的file对象进行判断,只有是目录时才可以作为子目录进行继续遍历
*/
File dirFile = new File("D:\VS 2019");
ListAll(dirFile);
System.out.println("一共有"+acount+"个文件和文件夹");
}
public static void ListAll(File dir) //dir用来接收待遍历的目录
{
File[] files = dir.listFiles();
for (File file2 : files) {
if(file2.isDirectory()) //如果遍历到当前的file对象是个目录,继续遍历,递归调用
{
ListAll(file2);
}
acount++;
System.out.println(file2.getName());
}
}
}
2、不使用递归获取一个目录下的所有子目录,既然不使用递归,那就需要考虑广度优先搜索,将目录加入一个队列,然后将文件直接输出文件名,然后出队第一个子目录,继续对其进行遍历,重复上述操作,即可获取全部内容。
public class exercise2 {
static int acount=0;
public static void main(String[] args)
{
/*
* 遍历文件夹,且不使用递归:
* 思路:
* 1、遍历test目录,将子目录存储到容器内
* 2、遍历容器。从容器中取出子目录,进行遍历
* 3、子目录中还有目录,继续存储,让遍历过的容器中的目录出队,释放容器空间
* 4、容器大小不确定,所以用集合
* 5、目录名有可能重复,所以用队列
*/
File dir = new File("D:\C++");
Queue<File> queue = new Queue<File>();
//1、对dir进行当前目录的遍历
File[]files = dir.listFiles();
for (File file : files)
{
//2、如果有子目录,存储到队列中
if(file.isDirectory())
{
acount++;
queue.myAdd(file);
}
else
{
acount++;
System.out.println(file.getName());
}
}
//3、遍历队列容器。因为子目录都在队列中
while(!queue.IsEmpty())
{
File[] files2 = queue.myRemove().listFiles();
for (File file : files2) {
if(file.isDirectory())
{
acount++;
queue.myAdd(file);
}
else {
System.out.println(file.getName());
acount++;
}
}
}
System.out.println("一共有"+acount+"个文件");
}
}
class Queue<E>
{
private LinkedList<E> link;
public Queue()
{
link = new LinkedList<E>();
}
public void myAdd(E obj)
{
link.addFirst(obj);
}
public E myRemove()
{
return link.removeLast();
}
public boolean IsEmpty()
{
return link.isEmpty();
}
}