File
File概述
File可以表示文件的路径也可以表示文件夹的路径
如果我们需要将一个游戏文件保存在本地,我们需要用File确定保存文件的位置和用IO进行传输
路径
File类构造方法
File表示文件,创建出一个对象则表示创建出了一个文件,而输出文件则输出路径名,则路径名是文件的字符串表示
package com;
import java.io.File;
public class FileDimo1 {
public static void main(String[] args) {
/*
public File(String pathname) 根据文件路径创建文件对象
public File(String parent,String child) 根据父类路径名字符串和子类路径名字符串创建文件对象
public File(File parent,String child) 根据父路径对应的文件对象和子路径名字符串创建文件对象
C:\Users\alienware\Desktop\a.txt
*/
//1.根据字符串表示的路径创建文件对象
String str = " C:\\Users\\alienware\\Desktop\\a.txt";
File f1 = new File(str);
System.out.println(f1.toString());// C:\Users\alienware\Desktop\a.txt
//2.根据父类路径字符串和子类路径字符串创建文件对象
//父级路径:C:\Users\alienware\Desktop
//子级路径:a.txt(完整文件名)
String parent = "C:\\Users\\alienware\\Desktop";
String child = "a.txt";
File f2 = new File(parent,child);
System.out.println(f2);//C:\Users\alienware\Desktop\a.txt
//这里也可以用父级路径名和子级路径名进行拼接(这种方式不提倡使用)
//1.java中\为文件分隔符有特殊含义需要用\\转义
//2.如果我们的代码用在别的平台 如Linux使用\\链接java底层将不会将文件分隔符转化为别的平台的分隔符
File f3 = new File("C:\\Users\\alienware\\Desktop"+"\\"+"a.txt");
System.out.println(f3);
//3.把一个File表示的路径和一个字符串表示的路径进行拼接
File parent2 = new File("C:\\Users\\alienware\\Desktop");
String child2 = "a.txt";
File f4 = new File(parent2,child);
System.out.println(f4);//C:\Users\alienware\Desktop\a.txt
}
}
绝对路径是带盘符的。相对路径是不带盘符的,默认到当前项目下去找
File中常见成员方法
判断获取
package com;
import java.io.File;
public class FileDimo1 {
public static void main(String[] args) {
//判断的方法
/*
public boolean isDirectory() 判断此路径名表示的File是否为文件夹
public boolean isFile() 判断此路径名表示的File是否为文件
public boolean exists() 判断此路径名表示的File是否存在
*/
//1.对一个文件的路径进行判断
File f1 = new File("D:\\QQLicense.rtf");
System.out.println(f1.isDirectory());//false
System.out.println(f1.isFile());//true
System.out.println(f1.exists());//true
System.out.println("----------------------------------------------------");
//2.对一个文件夹的路径进行判断
File f2 = new File("D:\\WeChat");
System.out.println(f2.isDirectory());//true
System.out.println(f2.isFile());//false
System.out.println(f2.exists());//true
System.out.println("-----------------------------------------");
//3.对一个不存在的路径进行判断
File f3 = new File("D:\\abcd");
System.out.println(f3.isDirectory());//false
System.out.println(f3.isFile());//false
System.out.println(f3.exists());//false
}
}
相对路径可以理解为在当前编译器项目中的路径,决定路径则是在整个电脑中的路径
定义File文件可以使用相对路径也可以使用绝对路径
package com;
import java.io.File;
public class FileDimo1 {
public static void main(String[] args) {
/*
获取方法:
public long length() 返回文件的大小(字节数量)
public String getAbsolutePath() 获取文件的绝对路径
public String getPath() 返回定义文件时使用的路径
public String getName() 返回文件的名称,带后缀
public long lastModified() 返回文件的最后修改时间(时间毫秒值)
*/
//1.length
/*
细节1:这个方法只能获取文件的大小(字节数量)
如果要得到M或者G 需要不断除以1024
细节2:这个方法无法获取文件夹的大小(文件夹调用该方法可能返回0或4096这和系统有关)
//如果要获取一个文件夹的大小,需要这个文件夹里面的所有文件的大小累加在一起
*/
File f1 = new File("D:\\QQLicense.rtf");//删除复制时的无关字符
final long len1 = f1.length();
System.out.println(len1);//253626
//当我们的File表示是文件夹时
File f2 = new File("D:\\Notepad++");
final long len2 = f2.length();
System.out.println(len2);//4096(这个答案并不正确)
System.out.println("-------------------------------------------------");
//2.返回文件的绝对路径getAbsolutePath()
File f3 = new File("D:\\Notepad++");//我们以绝对路径创建的对象
System.out.println(f3.getAbsoluteFile());//D:\Notepad++ 返回绝对路径
File f4 = new File("small\\aa.txt");//以相对路径定义
System.out.println(f4.getAbsoluteFile());//D:\ideaprojects\small\small\aa.txt(依然返回的是绝对路径)
//3.getPath() 返回定义文件时使用的路径(定义时写什么将会返回什么)
System.out.println("---------------------------------------------------------------");
File f5 = new File("D:\\Notepad++");//用绝对路径
System.out.println(f5.getPath());////D:\Notepad++
File f6 = new File("small\\aa.txt");//使用相对路径
System.out.println(f6.getPath());//small\aa.txt
System.out.println("----------------------------------------------------------------------");
//4.返回文件的名称getName
//细节:当是文件调用时 将会返回文件名+拓展名
//当是文件夹调用时,将会返回文件夹名
File f7 = new File("D:\\QQLicense.rtf");//文件
System.out.println(f7.getName());//QQLicense.rtf
File f8 = new File("D:\\Notepad++");//文件夹
System.out.println(f8.getName());//Notepad++
System.out.println("-----------------------------------------------------------");
//5.lastModified返回文件的最后修改时间
File f9 = new File("D:\\QQLicense.rtf");
final long time = f9.lastModified();
System.out.println(time);//1664518111254
}
}
创建和删除
package com;
import java.io.File;
import java.io.IOException;
public class FileDimo1 {
public static void main(String[] args) throws IOException {
/*
public boolean createNewFile() 创建一个新的空的文件
public boolean mkdir() 创建单级文件夹
public boolean mkdirs() 创建多级文件夹
public booean delete() 删除文件.空文件夹
*/
//1.createNewFile创建一个新的文件
/*
细节1:如果当前路径下创建的文件不存在则创建成功 方法返回true
如果当前路径下表示的文件存在则创建失败,方法返回false
细节2:如果父类路径是不存在的 方法将会抛出IOEXception
细节3:createNewFile方法创建的一定是文件 如果路径中的文件不含拓展名则创建的是不含拓展名的文件(和相同名称的文件不同)
*/
/*File f1 = new File("C:\\Data\\AAA");//定义一个文件
final boolean b = f1.createNewFile();//该处可能抛出异常
System.out.println(b);//第一次创建成功将返回true 再次创建将返回false*/
System.out.println("----------------------------------------------------------");
//2.mkdir make Directory 创建单级文件夹
/*
细节1:windows当中的路径是唯一的,如果当前的路径已经存在,则创建失败,返回false
细节2:mkdir方法只能创建单级文件夹,无法创建多级文件夹
*/
/* File f2 = new File("C:\\Data\\AAA");
final boolean c = f2.mkdir();
System.out.println(c);//此时AAA.txt和创建出来的文件夹路径相同
File f3 = new File("C:\\Data\\AAA\\AAA\\BBB");
final boolean d = f3.mkdir();//false
System.out.println(d);*/
System.out.println("-----------------------------------------------------------------");
//3.mkdirs
//细节:既可以创建单级文件夹又可以创建多级文件夹
/* File f5 = new File("C:\\Data\\bbb\\AAA\\BBB");//创建多级文件夹
System.out.println(f5.mkdirs());//true
File f6 = new File("C://Data\\ddd");//创建单级文件夹
System.out.println(f6.mkdirs());//true*/
//4.delete() 删除文件 文件夹
}
}
删除
package com;
import java.io.File;
public class FileDemo2 {
public static void main(String[] args) {
//public boolean delete() 删除文件 文件夹
/*
细节:如果删除的文件 则直接删除 不走回收站
如果删除的是文件夹:
如果是文件夹里面是空的 则直接删除 不走回收站
如果文件夹里面有内容 则无法删除
*/
//删除文件
File f1 = new File("C:\\Data\\AAA.txt");
System.out.println(f1.delete());//删除成功
//删除空文件夹
File f2 = new File("C:\\Data\\ddd");
System.out.println(f2.delete());//true
//删除有内容的文件夹
File f3 = new File("C::\\Data\\bbb");
System.out.println(f3.delete());//false 删除失败
}
}
获取并遍历
获取当前路径下的所有内容并放到一个数组中
package com;
import java.io.File;
public class FileDemo2 {
public static void main(String[] args) {
//public File[] listFiles() 获取当前路径下所有的内容
//1.创建File对象
File f = new File("C:\\Data\\bbb");
//2.调用listFilses方法 获取当前路径下所有的内容并放在数组中
File[] files = f.listFiles();
for (File file : files) {
System.out.println(file);
}
//如果当前路径下是文件则当前路径下没有内容 数组内容为空 增强for循环将会出现空指针异常
}
}
重点掌握:listFile方法的注意事项
重点掌握listFile其他的了解即可
package com;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
public class FileDemo2 {
public static void main(String[] args) {
/*
public static File[] listRoots() 列出可用的文件系统根
public String [] list() 获取当前该路径下的所有内容
public String [] list(FilenameFilter filter) 利用文件名过滤器获取当前该路径下的所有内容
(掌握)public File[] listFiles() 获取当前该路径下的所有内容
public File[] listFiles(FileFilter filter)利用文件名过滤器获取当前该路径下的所有内容
public File[] listFiles(FilenameFilter filter)利用文件名过滤器获取当前该路径下的所有内容
*/
//1.listRoots 获取系统中所有的盘符
// final File[] arr = File.listRoots();
//System.out.println(Arrays.toString(arr));//[C:\, D:\]
//2.list 获取当前该路径下所有内容(仅仅能获取名字,无法获取具体路径)
/* File f1 = new File("C:\\Data\\bbb");
final String[] arr2 = f1.list();
System.out.println(Arrays.toString(arr2));//[AAA, addd.txt, cwd]*/
//3.list(FilenameFilter filter)利用文件名过滤器获取当前该路径下所有内容
//需求:获取C:\\Data\\bbb文件夹里面所有的txt文件
/*
accept方法的形参,以此表示bbb文件夹中每一个文件或文件夹的路径
list的参数为一个函数式接口
参数一:父级路径
参数二:子级路径
返回值:如果返回值为true,就表示当前路径保留
如果返回值为false,则表示当前路径舍弃不要
*/
File f3 = new File("C:\\Data\\bbb");
String[]arr3 = f3.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {//分别表示父级路径和子级路径
File src = new File(dir,name);
if(src.isFile()&&name.endsWith("txt"))
return true;else {
return false;
}
}
});
System.out.println(Arrays.toString(arr3));//[addd.txt]
}
}
package com;
import java.io.File;
import java.util.Arrays;
public class FIleDemo3 {
public static void main(String[] args) {
/*
掌握)public File[] listFiles() 获取当前该路径下的所有内容
public File[] listFiles(FileFilter filter)利用文件名过滤器获取当前该路径下的所有内容
public File[] listFiles(FilenameFilter filter)利用文件名过滤器获取当前该路径下的所有内容
*/
//用listFiles获取txt文件
File f1 = new File("C:\\Data\\bbb");
final File[] arr = f1.listFiles();//获取当前路径下所有的内容
for (File file : arr) {
final String name = file.getName();//获取每一个文件或文件夹名
if(file.isFile()&&name.endsWith("txt")){
System.out.println(file);//C:\Data\bbb\addd.txt
}
}
}
}
后面的2个方法的参数都是函数式接口,并这2个方法实现过滤出txt文件和前面的一样
综合练习
练习1(创建文件)
package com;
import java.io.File;
import java.io.IOException;
public class FilePractice {
public static void main(String[] args) throws IOException {
/*
练习1:在C:\Data\bbb下中创建一个a.txt文件(bbb文件夹已经存在只需要创建文件)
练习1:在模块下的bbb文件夹中创建一个a.txt文件(模块下同时没有文件夹和文件都需要创建)
*/
//练习1
//创建文件的路径
/* File f = new File("C:\\Data\\bbb\\a.txt");
//在电脑中创建文件
boolean b = f.createNewFile();//此处要抛出异常
System.out.println(b);//true*/
//练习2
//我们需要先创建文件夹再创建文件
//定义文件夹的路径
File f2 = new File("small\\bbb");
final boolean b = f2.mkdirs();//创建文件夹
System.out.println(b);
//创建文件(可以使用子父级拼接也可以不使用)
//定义文件路径
File f3 = new File(f2, "a.txt");
//创建文件
final boolean c = f3.createNewFile();
System.out.println(c);
}
}
练习2(单个文件查找文件)
package com;
import java.io.File;
import java.io.IOException;
public class FilePractice {
public static void main(String[] args) throws IOException {
//定义一个方法找某一个文件夹中,是否有以avi结尾的电影(暂时不需要考虑子文件夹)
File f = new File("C:\\Data\\bbb");
final boolean b = havaAvi(f);
System.out.println(b);
}
//判断一个文件夹中是否有以avi结尾的电影
public static boolean havaAvi(File file){
final File[] files = file.listFiles();//得到该文件夹下所有的内容并放在数组中
for (File file1 : files) {//file1表示该文件夹里面每一个文件和文件夹的路径
final String name = file1.getName();//得到文件名或文件夹名
if(name.endsWith("avi")&&file1.isFile()){
return true;
}
}
return false;
}
}
练习3(遍历硬盘查找文件)
在所有的盘符中进行查找,难点在于各个文件夹包含的内容不统一,以至于代码无法统一编写
使用递归来解决
当引用数据类型指向null时,然后又使用该引用调用其堆空间的内容时,将会出现空指针异常
数组也是引用数据类型,可以用类来理解,int [] a ={}和int [] a = null意义不同,前者的有地址但是堆空间没有内容,后者则完全没有地址,用null调用堆空间内容将会出现空指针异常
package com;
import java.io.File;
import java.io.IOException;
public class FilePractice {
public static void main(String[] args) {
//找到电脑中所有以avi结尾的电影(需要考虑子文件夹)
//递归思想:把大问题拆分,拆到一个文件夹中不包含其他文件夹为止
/*
套路:
1.进入文件夹
2.遍历数组
3.判断
4.判断
*/
findAvi();
}
//该方法用于电脑上所有的盘符
public static void findAvi(){
final File[] files = File.listRoots();//获取电脑上所有的盘符
//遍历盘符
for (File file : files) {
findAvi(file);
}
}
//仅仅遍历c盘
public static void findAvi(File src){//假设传入c盘
//1.进入文件夹
File[] files = src.listFiles();//获取C盘下每一个文件或文件夹
//2.遍历数组
/*
细节:listFiles()方法当文件夹有访问权限时将会返回空
*/
if(files!=null){
for (File file : files) {//数组名指向空然后使用数组名调用堆空间内容将会出现空指针异常
//3.判断如果是文件执行具体业务逻辑
if(file.isFile()){
String name = file.getName();//获取文件名
if(name.endsWith("avi")){
System.out.println(file);
}
}else {//如果不是文件则进行递归继续向下查找
findAvi(file);
}
}
}
}
}
练习4
package com;
import java.io.File;
import java.io.IOException;
public class FilePractice {
public static void main(String[] args) {
/*
删除一个多级文件夹(文件夹里面有内容)
delete方法只能删除文件或者空文件夹
1.先删除文件夹里面的内容
2.然后删除自己
*/
File file = new File("C:\\Data");
remove(file);
}
/*
作用:删除bbb文件夹
参数:要删除的文件夹
*/
public static void remove(File file){
final File[] files = file.listFiles();//得到文件夹里面所有内容
if(files!=null){
for (File file1 : files) {
if(file1.isFile()){
file1.delete();
}else {
remove(file1);
}
}
file.delete();
}
}
}
练习5(统计文件夹的大小)
package com;
import java.io.File;
import java.io.IOException;
public class FilePractice {
public static void main(String[] args) {
//统计一个文件夹的总大小
File file = new File("C:\\Data");
System.out.println(getLen(file));
}
/*
文件夹总大小:文件夹里面所有文件的总大小
形参表示要统计的文件夹
*/
public static long getLen(File src){
//1.进入文件夹
long len = 0;//用于统计总大小(单位字节)
final File[] files = src.listFiles();
//2.遍历数组
for (File file : files) {
if(file.isFile()){
final long length = file.length();//获取文件的大小
len = len + length;
/*
对于len= len+length的细节:
len为一个函数里面的局部变量
当递归再次调用函数的时候 递归函数的len和没有递归的len不是同一个len
所有返回的len仅仅是src文件夹里面的文件总大小
*/
}else {
//如果是文件夹则进行递归处理
//修改前:getLen(file)
len = len + getLen(file);//修改后
//如果递归把文件夹文件总和返回并和以前的总和一个累加
}
}
return len;
}
}
练习6(统计各种文件夹的数量)(有点难度要使用Map集合)
package com;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class FilePractice {
public static void main(String[] args) {
//统计一个文件夹中每种文件的个数并打印(考虑子文件夹)
/*
打印格式如下:
txt:3个
doc:4个
jpg:6个
用到知识:File 递归 Map(用于统计)(键文件,值:数量)
计数器思想的弊端:不知道文件夹中有多少种文件 则不知道需要设置多少个计数器变量
*/
File file = new File("C:\\Data");
final HashMap<String, Integer> count = getCount(file);
System.out.println(count);
}
/*
作用:统计一个文件夹中每种文件的个数
参数:要统计的文件夹
返回值:
用来统计的map集合
键:文件名 值:次数
要考虑到的文件名:
a.txt
a.a.txt
aaa(这种文件名不需要统计)
*/
public static HashMap<String,Integer> getCount(File file){
//1.定义集合用于统计
HashMap<String,Integer> hm = new HashMap<>();
//2.进入Data文件夹
final File[] files = file.listFiles();//得到文件中所有的内容
//3.变量数组
for (File file1 : files) {
if(file1.isFile()){
//当为文件时
final String name = file1.getName();//得到文件名
final String[] arr = name.split("\\.");//按照点进行分割
if(arr.length>=2){//数组长度大于等于2则需要统计
String endName = arr[arr.length-1];//得到最大索引上的元素即后缀名
if(hm.containsKey(endName)){
//如果该文件已经被统计
Integer count = hm.get(endName);//得到该文件出现的次数
count++;
hm.put(endName,count);
}else {
//该文件没有被统计过
hm.put(endName,1);
}
}
}else{
//当为文件夹时进行递归处理
//sonMap里面是子文件夹中每一种文件的个数
HashMap<String, Integer> sonMap = getCount(file1);
//将sonMap中的数量同步到hm中
//1.遍历sonMap集合把里面的值累加到hm中
final Set<Map.Entry<String, Integer>> entries = sonMap.entrySet();//放在set中
for (Map.Entry<String, Integer> entry : entries) {
final String key = entry.getKey();
final Integer value = entry.getValue();
if(hm.containsKey(key)){
//hm中存在该键
Integer count = hm.get(key);//得到hm中该键的值
count = count +value;//将该键的值累加
hm.put(key,count);//将hm中这对键和值更新
}else {
//hm中不存在该键
hm.put(key,value);//不存在直接放入
}
}
}
}
return hm;
}
}