File类概述
- 先要定位文件
- File类可以定位文件:进行删除:获取文本本身信息等操作
- 但是不能读写文件内容 - 读写文件数据
- IO流技术可以对硬盘中的文件进行读写
- File类在包java.io.File下、代表操作系统文件对象(文件、文件夹)
- File类提供了诸如:定位文件,获取文件本身的信息,删除文件、创建文件(文件夹)等功能
- delete方法默认只能删除空文件夹
public static void main(String[] args) {
//1.创建File对象(指定文件的路径)
File f=new File("D:\\我的文件\\证书及成绩单\\2021.12数学省赛.jpg");
//File file=new File("D:"+File.separator+"我的文件"+File.separator+"证书及成绩单"+File.separator+"2021.12数学省赛.jpg");
long size=f.length();
System.out.println(size);
//2.File创建对象,支持绝对路径,支持相对路径(重点)
File f1=new File(" D:\\我的文件\\证书及成绩单\\2021.12数学省赛.jpg");//绝对路径
System.out.println(f1.length());
//相对路径:一般定位模块中的文件的.相对到工程下
File f2=new File("file-io-app/src/data.txt");
System.out.println(f2.length());
//File创建对象,可以是文件也可以是文件夹
File f3=new File("D\\resource");
System.out.println(f3.exists());
//获取绝对路径
System.out.println(f.getAbsoluteFile());
//获取文件定义的时候使用的路径
System.out.println(f.getPath());
//获取文件的名称:带后缀
System.out.println(f.getName());
//获取文件最后修改的时间
long time=f.lastModified();
System.out.println("文件最后修改时间:"+new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(time));
//判断文件是文件还是文件夹
System.out.println(f.isFile());
System.out.println(f.isDirectory());
//创建多级目录
File f5=new File("D/aaa/bbb/ccc/ddd");
System.out.println(f5.mkdirs());
}
File类的遍历功能
litFiles方法注意事项
- 当调用者不存在时,返回null
- 当调用者是一个文件时,返回null
- 当调用者时一个空文件夹时,返回一个长度为0的数组
- 当调用者是一个有内容的文件夹时。将里面搜有文件和文件夹的路径放在File数组中返回
- 当调用者是一个有隐藏文件的文件夹,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏内容
- 当调用者是一个需要权限才能进入的文件夹时,返回null
public static void main(String[] args) {
//1.定义一个目录
File f1=new File("D:/我的文件");
String[] names=f1.list();
for(String name:names){
System.out.println(name);
}
//2.一级文件对象
//获取当前目录下所有的”一级文件对象“到一个文件对象数组中去返回(重点)
File[] files=f1.listFiles();
for (File f:files){
System.out.println(f.getAbsoluteFile());
}
File dir=new File("D:/resource");
File[] files1=dir.listFiles();
System.out.println(files1);
}
方法递归
- 方法直接调用自己或者调用自己的形式称为方法递归(recursion)
- 递归作为一种算法在程序设计语言中广泛应用
递归的形式 - 直接递归:方法自己调用自己
- 间接递归:方法调用其他方法,其他方法又调回方法自己
需求:计算1-n的阶乘的结果,使用递归思想解决,我们先从数学思维上理解递归的流程和核心点
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
System.out.println(resu(n));
}
private static int resu(int n) {
if(n==1)
return 1;
else
return n*resu(n-1);
}
猴子吃桃问题
一只小猴子一天摘了许多桃子,第一天吃了一半,然后忍不住又吃了一个;第二天又吃了一半,再加上一个;后面每天都是这样吃。到第10天的时候,小猴子发现只有一个桃子了。问小猴子第一天共摘了多少个桃子。
public class RecusionDemo3 {
//f(x+1)=f(x)-f(x)/2-1
//f(x)+2*f(x+1)+2
public static void main(String[] args) {
System.out.println(f(1));
}
private static int f(int i) {
if(i==10)
return 1;
else
return 2*f(i+1)+2;
}
}
文件搜索: 从C盘中,搜索出某个文件名称并输出绝对路径
分析:
1. 先定位出的应该是以及文件对象
2. 遍历全部以及文件对象,判断是否是文件
3. 如果是文件,判断是否是自己想要的
4. 如果是文件夹,需要继续提柜进入重复上述过程
public class RecusionDemo4 {
public static void main(String[] args) {
searchFile(new File("D:/"),"国赛.jpg");
}
private static void searchFile(File dir, String fileName) {
if(dir!=null&&dir.isDirectory()){
File[] files=dir.listFiles();
if(files!=null&&files.length>0){//先判断是否为null再判断是否为0
//可以寻找
for(File file:files){
if(file.isFile()){
if(file.getName().contains(fileName)){
System.out.println("找到了"+file.getAbsoluteFile());
break;
}
}else
searchFile(file,fileName);
}
}
}else
System.out.println("当前寻找的不是文件夹");
}
}
啤酒问题:
啤酒2元一瓶,4个盖子可以换一瓶,2个空瓶可以换1瓶。请问10元钱可以和多少就,剩余多少空瓶和盖子
答案:15瓶 3盖子 1瓶子
public static int totalNumber;//默认值为0
public static int lastBottleNumber;
private static int lastCoverNumber;
public static void main(String[] args) {
int money=10;
int bottle=money/2;
int empty_bottle=5;
int lid=5;
buy(money);
System.out.println("一共"+totalNumber+"瓶酒 "+lastCoverNumber+"个盖子 "+lastBottleNumber+"个空瓶");
}
private static void buy(int money) {
int buyNumber=money/2;
totalNumber+=buyNumber;
int bottleNumber = lastBottleNumber+buyNumber;
int coverNumber =lastCoverNumber+buyNumber;
int allMoney=0;
if(coverNumber>=4){
allMoney+=coverNumber/4*2;
}
lastCoverNumber=coverNumber%4;
if(bottleNumber>=2){
allMoney+=bottleNumber/2*2;
}
lastBottleNumber=coverNumber%2;
if (allMoney>=2)
buy(allMoney);
}
IO流
IO流也称为输入、输出流,就是用来读写数据的
- I表示input,是数据从硬盘文件读入到内存的过程,称之输入,负责读
- O表示output,是内存程序的数据从内存到写出硬盘文件的过程,称之输出,负责写
总结流的四大类 - 字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流称为字节输入流
- 字节输出流:以内存为基准,把内存中的数据以字节写到磁盘文件或者网络中去的流称为字节输出流
- 字符输入流:以内存为基准,来自磁盘文件/网络的数据以字符的形式读入到内存中去的流称为字符输入流
- 字符输出流:以内存为基准,把内存中的数据以字符写到磁盘文件或者网络介质中去的流称为字符输出流
public static void main(String[] args) throws IOException {
//1.创建一个文件字输入流管道与源文件接通
//InputStream is=new FileInputStream(new File("file-io-app\\src\\data.txt"));
//简化写法
InputStream is=new FileInputStream("file-io-app\\src\\data.txt");
// //2.读取一个字节返回
// int b1=is.read();
// System.out.println((char) b1);
// //读取了下一给字符,如果读取完毕返回-1
// int b2=is.read();
// System.out.println((char) b2);
int b;
while((b=is.read())!=-1){
System.out.println((char)b);
}
}
- 如何使用字节输入流读取中文内容输出不乱码
- 定义一个与文件一样大的数组,一次性读取完文件的全部字节
- 直接把文件数据全部读取到一个字节数组可以避免乱码,是否存在问题
- 如果文件过大,字节数组可能引起内存溢出
字节输入流写数据的方法
public static void main(String[] args) throws IOException {
//1.创建一个文件字输入流管道与源文件接通
//InputStream is=new FileInputStream(new File("file-io-app\\src\\data.txt"));
//简化写法
//OutputStream os=new FileOutputStream("file-io-app\\src\\data.txt",true);//表示在后面追加数据
OutputStream os=new FileOutputStream("file-io-app\\src\\data.txt");//先清空之前的数据,写新数据进入
//写数据
os.write('a');
os.write(90);
os.write("\r\n".getBytes());
//os.write('徐');//乱码
byte[] buffer={'a',97,98,99};
os.write(buffer);
byte[] buffer2="我是中国人".getBytes();
os.write(buffer2);
byte[] buffer3={'a',97,98,99};
os.write(buffer,0,3);
os.flush();//写数据一定要刷新数据,可以继续使用流
os.close();//释放资源,包含了刷新将内存空间释放出来,关闭之后流不能使用
}
字节流数据如何实现数据追加public FileOutputStream(String filepath,boolean append)
创建字节输出流管道与源文件路径接通可追加数据
字节输出流如何实现写出去的数据能换行
os.wirte("\r\n".getBytes());
文件拷贝
需求:把某个视频复制到其他目录下的b.avi
①. 根据数据源创建字节输入流对象
②. 根据目的地创建字节输出流对象
③. 读写数据,复制视频
④. 释放资源
字节流适合做一切文件数据的拷贝
- 任何文件的底层都是字节,拷贝是一起不漏的转移字节,只要前后文件格式、编号一直没有任何问题
资源释放的方式
try-catch-finally
- finally:在异常处理时提供finally块来执行所有清除操作,比如说IO流中的释放资源
- 特点:被finally控制的语句最终一定会执行,除非JVM退出
- 异常处理格式:try-catch-finally
try-catch-finally格式
finally代码是最终一定要执行的,可以在代码执行完毕的最后用于释放资源,finally语句在return语句前执行。除非在之前使用exit退出虚拟机,那么就不执行
public class TryCatchFinallyDemo1 {
public static void main(String[] args) throws IOException {
System.out.println(test(110,0));
}
public static int test(int a,int b){
//return在finally后执行
try {
int c=a/b;
return c;
}catch (Exception e){
e.printStackTrace();
return -1111;//计算出bug
}finally {
//哪怕上面有return语句执行,也必须先执行完这里的才可以
//开发中不建议在这里加return,如果加了,返回的永远是这里的数据了,这样会出问题!
//return 100;
System.out.println("++++++++++++");
}
}
}
字符流的使用
- 字节流输出存在的问题
- 会乱码。或者内存溢出 - 读取中文输出,哪个流更合适,为什么?
- 字符流更合适,最小单位是按照单个字符读取的
文件字符输入流-一次读取一个字符
文件字符输入流:Reader
- 作用:以内存为基准,把磁盘文件中的数据以字符的形式读取到内存中去
字符流的好处:读取中文的时候不会乱码(如果代码和文件编码一致)
性能较慢
文件字符输入流-一次读取一个字符数组
public static void main(String[] args) throws Exception {
//目标:每次读取一个字符
//1.创建一个字符输入流管道与源文件接通
Reader fr=new FileReader("file-io-app\\src\\data.txt");
//2.读取一个字符返回,美欧刻度的字符返回-1
// int code =fr.read();
// System.out.println((char)code);
// int code1=fr.read();
// System.out.println((char)code1);
//3.循环读取字符
int code;
while ((code= fr.read())!=-1){
System.out.println((char)code);
}
}
文件字符输出流
public static void main(String[] args) throws Exception {
//1.创建一个字符输出流管与目标文件接通
Writer fw=new FileWriter("file-io-app\\src\\data.txt");
//覆盖管道,每次启动都会清空文件之后的数据
fw.write("潘潘潘");
char[] chars="abc".toCharArray();
fw.write(chars);
fw.write("adasda",0,5);
}