学习目标
- 能够说出File对象的创建方式(必须会)
使用构造方法
public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。
- 能够使用File类常用方法(必须会)
public String getName() :获取构造方法中路径的名称(末尾部分)
public String getAbsolutePath() : 获取构造方法中路径的绝对路径
public long length() :获取文件的大小,单位是字节
public boolean isDirectory() :是否为目录(文件夹)。
public boolean exists() :判断构造方法中传递的路径是否存在
public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
public boolean mkdir() :创建单级文件夹
public boolean mkdirs() :即可以创建单级文件夹,又可以创建多级文件夹
public boolean delete() :删除文件和文件夹,不走回收站
- 能够辨别相对路径和绝对路径(必须会)
绝对:以盘符开始
相对:相对当前项目的根目录而言;使用项目的跟目录可以省略书写(不是盘符开始)
绝对:D:\\Work_idea\\EE132\\day15\\a.txt
相对:day15\\a.txt
项目的根目录 D:\\Work_idea\\EE132
- 能够遍历文件夹(必须会)
public String[] list() :
遍历构造方法传递的文件夹,获取文件夹中每一个文件|子文件夹的名称,把多个名称存储到一个String类型的数组中返回
public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。
遍历构造方法传递的文件夹,获取文件夹中每一个文件|子文件夹,把文件|子文件夹封装为File对象,多个File对象存储到一个File类型的数组中返回
- 能够解释递归的含义
方法自己调用自己
- 能够使用递归的方式计算5的阶乘(必须会)
public static int jc(int n) {//方法的主体不变,每次调用自己参数在发生变化5,4,3,2,1
//递归结束的条件:获取到1的时候结束
if(n==1){
return 1;
}
//递归的目的:获取下一个被乘的数字n-1
return n * jc(n-1);
}
- 能够说出使用递归会内存溢出隐患的原因
方法自己调用自己,没有结束条件,栈内存中会有无数多个方法,如果方法过多超出了栈内存是范围就会发生内存溢出
- 能够说出IO流的分类和功能
输入流:把硬盘(U盘,移动硬盘,磁盘,光盘...)上的数据读取到内存中
字符输入流:读取字符
字节输入流:读取字节
输出流:把内存中的数据写入到硬盘中(U盘,移动硬盘,磁盘,光盘...)
字符输出流:写入字符
字节输出流:写入字节
- 能够使用字节输出流写出数据到文件(必须会)
1.创建FileOutputStream对象,构造方法中传递写入数据的目的地
2.调用FileOutputStream对象中的方法write,把数据写入到文件中
3.释放资源
FileOutputStream fos = new FileOutputStream("day10\\1.txt");
fos.write(97);
fos.close();
- 能够使用字节输入流读取数据到程序
1.创建FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("day15\\a.txt");
2.FileInputStream对象中的方法read,以字节的方式读取文件
int len = 0;
while ((len = fis.read())!=-1){
System.out.print((char)len);
}
3.释放资源
fis.close();
- 能够理解读取数据read(byte[])方法的原理
1.read方法的参数byte[]字节数组的作用?
起到缓冲作用,把读取到的字节依次存储到数组中
把数组一次性的由操作系统返回给JVM,由JVM返回给java程序,效率高
数组的长度一般都使用:1024或者1024的整数倍
2.read方法的返回值int是什么?
每次读取到的有效字节个数
FileInputStream fis = new FileInputStream("day15\\a.txt");
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes))!=-1){
System.out.print(new String(bytes,0,len));
}
fis.close();
- 能够使用字节流完成文件的复制(一读一写)
1.创建FileInputStream对象,构造方法中绑定要读取的数据源
2.创建FileOutputStream对象,构造方法中绑定要写的目的地
3.使用FileInputStream对象中的方法read,以字节的方式读取文件
4.使用FileOutputStream对象中的方法write,把读取到的字节写入到文件中
5.释放资源
第一章 File类
1.File类的介绍
java.io.File类
文件和目录路径名的抽象表示形式。
把计算机中的文件和文件夹(目录)封装为了File对象,就可以使用File对象来操作这些文件和文件夹
我们可以使用File对象创建文件和文件夹
我们可以使用File对象删除文件和文件夹
我们可以使用File对象获取文件和文件夹的路径
我们可以使用File对象获取文件的大小(单位是字节)
我们可以使用File对象遍历文件夹
记住3个相关的单词:
1.file:文件
2.directory:文件夹(目录)
3.path:路径
2.路径
路径:表示存储文件和文件夹的路径(位置)
分类:
1.绝对路径:以盘符开始的路径(c:,d:,e:)
c:\\1.jpg d:\\aaa\\a.txt D:\\Work_idea\\EE141\\day10
2.相对路径:相对于当前项目的根目录而言,我们使用路径,可以省略项目的根目录
项目的根目录:D:\\Work_idea\\EE119
EE119:创建的一个项目
注意:大家的项目根目录都不同
a.绝对路径[必须包含项目的根目录]才可以省略
D:\\Work_idea\\EE119\\day10 可以省略为 day10
D:\\Work_idea\\EE119\\day10\\a.txt 可以省略为 day10\\a.txt
c:\\1.jpg 不能省略
1.jpg==> D:\Work_idea\EE119\\1.jpg
abc\\bbc\\ccc\\abc.java==>D:\\Work_idea\\EE119\\abc\\bbc\\ccc\\abc.java
b.当我们省略书写项目的根目录,java会在相对路径前默认给添加上
注意:
1.路径是不区分大小写的 c:\\1.jpg 等价 C:\\1.jpg
2.路径中目录的分割的符号\必须的写两个\\,\本身是一个转义字符,必须的写两个代表一个\
3.路径中目录的分割的符号也可以使用一个正斜杠/ c:\\a.txt 等价 c:/a.txt
3.File的构造方法(重点)
package com.itheima.demo01File;
import java.io.File;
/*
File的构造方法(重点)
*/
public class Demo01FileConstructor {
public static void main(String[] args) {
show02("d:\\aaa","a.txt");//d:\aaa\a.txt
show02("c:\\","a.txt");//c:\a.txt
show02("c:\\","aaa\\bbb\\ccc");//c:\aaa\bbb\ccc
show03();
}
/*
File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
参数:把路径分成了两部分
File parent:父路径
String child:子路径
好处:
创建File对象的时候,父路径和子路径分别指定,可以组成不同的路径
*/
private static void show03() {
File parent = new File("d:\\aaa");
File file = new File(parent,"a.txt");
System.out.println(file);//d:\aaa\a.txt
}
/*
File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
参数:把路径分成了两部分
String parent:父路径
String child:子路径
好处:
创建File对象的时候,父路径和子路径分别指定,可以组成不同的路径
*/
private static void show02(String parent, String child) {
File file = new File(parent,child);
System.out.println(file);
}
/*
File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
参数:
String pathname:传递一个路径名称
注意:
1.传递的路径名称可以是绝对路径,也可以是相对路径
2.传递的路径名称可以以文件结尾,也可以使用以文件夹结尾
3.传递的路径名称可以是计算机中真实存在的,也可以是瞎编乱造的
构造方法仅仅是把字符串的路径封装为File对象,不考虑路径的真实情况
*/
private static void show01() {
File f1 = new File("c:\\1.jpg");
System.out.println(f1);//c:\1.jpg 不是对象的地址值,File类重写了Object类的toString方法
File f2 = new File("D:\\Work_idea\\EE169\\day10");
System.out.println(f2);//D:\Work_idea\EE169\day10
File f3 = new File("day10");
System.out.println(f3);//day10
File f4 = new File("day10/aaa/bbb/cc/ddd");
System.out.println(f4);//day10\aaa\bbb\cc\ddd
}
}
4.File类的成员方法_获取功能的方法(重点)
public String getAbsolutePath() :返回此File的绝对路径名字符串。
public String getPath() :将此File转换为路径名字符串。
public String getName() :返回由此File表示的文件或目录的名称。
public long length() :返回由此File表示的文件的长度。 不能获取目录的长度
package com.itheima.demo01File;
import java.io.File;
/*
File类获取相关的方法
*/
public class Demo02FileMethod {
public static void main(String[] args) {
show04();
}
/*
public long length() :返回由此File表示的文件的大小。 不能获取目录的大小。
注意:
1.文件大小的单位是字节
2.此方法只能获取文件大小,不能获取文件夹大小(文件夹没有大小概念)
如果此路径名表示一个目录(文件夹),则返回值是不确定的。
3.如果文件不存在,则返回 0L
*/
private static void show04() {
File f1 = new File("D:\\base\\20210908EE169\\day10-File类、递归、字节流\\day10课件\\day10-File类、递归、字节流.pptx");
System.out.println(f1.length());//3092266字节
File f2 = new File("day10\\1.jpg");
System.out.println(f2.length());//161,548 字节
File f3 = new File("day10\\2.jpg");
System.out.println(f3.length());//0L 文件不存在
File f4 = new File("D:\\Work_idea\\EE169\\day10");
System.out.println(f4.length());//0 4096文件夹没有大小概念的
}
/*
public String getName(): 获取构造方法中路径末尾的名称
*/
private static void show03() {
File f1= new File("D:\\Work_idea\\EE169\\day10");
System.out.println(f1.getName());//day10
File f2 = new File("c:\\aaa\\1.jpg");
System.out.println(f2.getName());//1.jpg
}
/*
public String getPath() :返回构造方法中传递的路径
构造方法中传递的路径是绝对的,就返回绝对路径
构造方法中传递的路径是相对的,就返回相对路径
File类重写了Object类的toString方法
public String toString() {
return getPath();
}
*/
private static void show02() {
File f1= new File("D:\\Work_idea\\EE169\\day10");
System.out.println(f1.getPath());//D:\Work_idea\EE169\day10
File f2 = new File("day10");
System.out.println(f2.getPath());//day10
System.out.println(f2);//day10
System.out.println(f2.toString());//day10
}
/*
Absolute:绝对的
public String getAbsolutePath() :获取构造方法中传递路径的绝对路径。
构造方法中传递的路径是绝对的,直接返回绝对路径
构造方法中传递的路径是相对的,会在相对路径前添加项目根目录,组成绝对路径返回
*/
private static void show01() {
File f1 = new File("c:\\1.jpg");
System.out.println(f1.getAbsolutePath());//c:\1.jpg
File f2 = new File("D:\\Work_idea\\EE169\\day10");
System.out.println(f2.getAbsolutePath());//D:\Work_idea\EE169\day10
File f3 = new File("day10");
System.out.println(f3.getAbsolutePath());//D:\Work_idea\EE169\day10
}
}
5.File类的成员方法_判断功能的方法(重点)
public boolean exists() :此File表示的文件或目录是否实际存在。
public boolean isDirectory() :此File表示的是否为目录。
public boolean isFile() :此File表示的是否为文件。
package com.itheima.demo01File;
import java.io.File;
/*
File类的成员方法_判断功能的方法(重点)
public boolean exists() :此File表示的文件或目录是否实际存在。
public boolean isDirectory() :此File表示的是否为目录。
public boolean isFile() :此File表示的是否为文件。
*/
public class Demo03FileMethod {
public static void main(String[] args) {
show02();
}
/*
public boolean isDirectory() :判断构造方法中传递的路径是否以文件夹结尾
返回值:boolean
是以文件夹结尾:返回true
不是以文件夹结尾:返回false
public boolean isFile() :判断构造方法中传递的路径是否以文件结尾
返回值:boolean
是以文件结尾:返回true
不是以文件结尾:返回false
注意:
1.以上两个方法判断的前提,是这个路径必须是真实存在的,否则都返回false
2.计算机中除了文件就是文件夹,所有两个方法互斥
*/
private static void show02() {
File f1 = new File("c:\\adsfdsafdsa");
System.out.println(f1.isDirectory());//false
System.out.println(f1.isFile());//false
System.out.println("--------------------------------");
File f2 = new File("c:\\1.jpg");
if(f2.exists()){
System.out.println(f2.isDirectory());//false
System.out.println(f2.isFile());//true
}
System.out.println("--------------------------------");
File f3 = new File("day10");
if(f3.exists()){
System.out.println(f3.isDirectory());//true
System.out.println(f3.isFile());//false
}
}
/*
public boolean exists() :此File表示的文件或目录是否实际存在。
返回值:boolean
构造方法中的文件|文件夹存在,返回true
构造方法中的文件|文件夹不存在,返回false
*/
private static void show01() {
File f1 = new File("c:\\1.jpg");
System.out.println(f1.exists());//true
File f2 = new File("day10");
System.out.println(f2.exists());//true
File f3 = new File("day10\\aaa");
System.out.println(f3.exists());//false
}
}
6.File类的成员方法_创建删除功能的方法(重点)
public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
public boolean mkdir() :创建由此File表示的目录。
public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
public boolean delete() :删除由此File表示的文件或目录。
package com.itheima.demo01File;
import java.io.File;
import java.io.IOException;
/*
File类的成员方法_创建删除功能的方法(重点)
public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
public boolean mkdir() :创建由此File表示的目录。
public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
public boolean delete() :删除由此File表示的文件或目录。
*/
public class Demo04FileMethod {
public static void main(String[] args) throws IOException {
show03();
}
/*
delete:删除
public boolean delete() :删除构造方法中路径指向的文件|文件夹
返回值:boolean
文件|文件夹存在,删除成功,返回true
文件|文件夹不存在,删除失败,返回false
文件夹中有数据,删除失败,返回false
注意:
此删除方法不走回收站,直接在硬盘删除,需要谨慎
*/
private static void show03() {
File f1 = new File("day10\\1.txt");
boolean b1 = f1.delete();
System.out.println("b1:"+b1);
File f2 = new File("day10\\aaa");
boolean b2 = f2.delete();
System.out.println("b2:"+b2);
File f3 = new File("day10\\111");
boolean b3 = f3.delete();
System.out.println("b3:"+b3);
}
/*
mk:make 制造,创建 dir:directory 文件夹
public boolean mkdir() :只能创建单级文件夹
public boolean mkdirs() :既能创建单级文件夹,又能创建多级文件夹
返回值:boolean
文件夹不存在,创建成功,返回true
文件夹已经存在,不会创建(覆盖),创建失败,返回false;路径不存在,返回false
注意:
1.创建文件夹的路径和名称在构造方法中给出
2.以上两个方法只能创建文件夹,不能创建文件
*/
private static void show02() {
File f1 = new File("day10\\aaa");
boolean b1 = f1.mkdir();
System.out.println("b1:"+b1);
File f2 = new File("day10\\111\\222\\333\\444\\555");
boolean b2 = f2.mkdirs();
System.out.println("b2:"+b2);
File f3 = new File("e:\\name");
boolean b3 = f3.mkdir();
System.out.println("b3:"+b3);//b3:false 路径不存在
}
/*
create:创建,新建 new:新的 File:文件
public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
返回值:boolean
文件不存在,创建成功,返回true
文件已经存在,不会创建(覆盖),创建失败返回false
注意:
1.创建文件的路径和名称在构造方法中给出
2.此方法只能创建文件,不能创建文件夹
3.创建文件的路径不存在,会抛出异常
4.有些操作系统的c盘,没有权限创建文件,会抛出异常
*/
private static void show01() throws IOException {
File f1 = new File("d:\\a.txt");
boolean b1 = f1.createNewFile();
System.out.println("b1:"+b1);
File f2 = new File("day10\\1.txt");
boolean b2 = f2.createNewFile();
System.out.println("b2:"+ b2);
File f3 = new File("e:\\2.txt");
//boolean b3 = f3.createNewFile();//IOException: 系统找不到指定的路径。
File f4 = new File("d:\\abcsafa\\3.txt");
//boolean b4 = f4.createNewFile();//IOException: 系统找不到指定的路径。 abcsafa文件夹不存在
}
}
7.File类的成员方法_目录遍历的方法(重点)
package com.itheima.demo01File;
import java.io.File;
/*
File类的成员方法_目录遍历的方法(重点)
目录也叫文件夹
String[] list() 用于遍历目录,获取目录中每一个文件|文件夹的名称,把多个名称存储到一个String类型的数组中返回
File[] listFiles() 用于遍历目录,获取目录中每一个文件|文件夹,会把文件|文件夹封装为File对象,把多个File对象存储到一个File类型的数组中返回
注意事项:
1.要遍历的目录的路径在构造方法中给出
2.以上两个方法只能遍历目录,不能遍历文件,会抛出空指针异常
3.遍历目录的路径不存在,会抛出空指针异常
*/
public class Demo05FileMethod {
public static void main(String[] args) {
//File file = new File("e:\\aaa");//NullPointerException
//File file = new File("d:\\aaa\\1.jpg");//NullPointerException
File file = new File("D:\\aaa");
String[] arr = file.list();
System.out.println(arr);
//在工作中,遍历数组和集合之前,都要增加非空判断,防止空指针异常
if(arr!=null && arr.length>0){
for (String fileName : arr) {
System.out.println(fileName);
}
}
System.out.println("-------------------");
File[] files = file.listFiles();
System.out.println(files);
if(files!=null && files.length>0) {
for (File f : files) {
System.out.println(f);
}
}
}
8.File类目录遍历综合练习题
package com.itheima.demo01File;
import java.io.File;
import java.util.Scanner;
/*
File类目录遍历综合练习题
需求:
键盘录入一个文件路径,根据文件路径创建File对象,判断是文件还是文件夹
如果是文件,则输出文件的大小
如果是文件夹,则计算该文件夹下所有文件大小之和并输出(不包含子文件夹)。
分析:
1.创建键盘录入Scanner对象
2.接收键盘录入的字符串路径
3.根据字符串路径创建文件对象
4.判断文件对象是文件还是文件夹,如果是文件,则直接输出文件大小
5.如果是文件夹
5.1定义一个求和变量,记录累加求和
5.2遍历文件夹,获得该文件夹下所有的文件
5.3获取文件大小,累加到求和变量中
5.4最后输出求和变量的值。
*/
public class Demo06FileTest {
public static void main(String[] args) {
//1.创建键盘录入Scanner对象
Scanner sc = new Scanner(System.in);
//2.接收键盘录入的字符串路径
System.out.println("请输入一个文件|文件夹的路径:");
String path = sc.nextLine();
//3.根据字符串路径创建文件对象
File file = new File(path);
//判断file是否存在
if(file.exists()){
//4.判断文件对象是文件还是文件夹,
if(file.isFile()){
//如果是文件,则直接输出文件大小
System.out.println("您输入的路径是一个文件,文件的大小是:"+file.length()+"字节");
}else{
//5.如果是文件夹
//5.1定义一个求和变量,记录累加求和
long sum = 0;
//5.2遍历文件夹,获得该文件夹下所有的文件
File[] files = file.listFiles();
//防止空指针异常,遍历数组增加非空判断
if(files!=null && files.length>0){
for (File f : files) {
//5.3获取文件大小,累加到求和变量中
sum+=f.length();
}
}
//5.4最后输出求和变量的值。
System.out.println("您输入的路径是一个文件夹,文件夹中所有文件的大小为:"+sum+"字节");
}
}else{
System.out.println("您输入的路径不存在!");
}
}
}
第二章 递归
1.递归的概述
递归:方法自己调用自己
分类:
1.直接递归
public void a(){
a();
}
2.间接递归
public void a(){
b();
}
public void b(){
a();
}
注意事项:
1.递归必须有结束的条件,保证方法自己调用自己能停止下来,否则会抛出栈内存溢出的错误
2.递归有结束的条件,但是递归的次数也不能太多了,否则会抛出栈内存溢出的错误
3.构造方法禁止递归
什么时候使用递归:
当我们频繁的调用一个方法,方法的主体不变,方法的参数每次发生变化,就可以使用递归
package com.itheima.demo02Recursion;
/*
递归的注意事项:
1.递归必须有结束的条件,保证方法自己调用自己能停止下来,否则会抛出栈内存溢出的错误
2.递归有结束的条件,但是递归的次数也不能太多了,否则会抛出栈内存溢出的错误
3.构造方法禁止递归
*/
public class Demo01DiGui {
public static void main(String[] args) {
//a();
b(1);
}
/*
3.构造方法禁止递归
*/
public Demo01DiGui() {
//Demo01DiGui();
}
/*
2.递归有结束的条件,但是递归的次数也不能太多了,否则会抛出栈内存溢出的错误
11413 11410 方法的数量不是绝对的,内存的使用率随时在变化
Exception in thread "main" java.lang.*Error
*/
private static void b(int i) {
System.out.println(i);
if(i==20000){
return;//结束方法
}
b(++i);
}
/*
1.递归必须有结束的条件,保证方法自己调用自己能停止下来,否则会抛出栈内存溢出的错误
Exception in thread "main" java.lang.*Error
*/
private static void a() {
System.out.println("a方法");
a();
}
}
2.练习:使用递归计算1-n的和
package com.itheima.demo02Recursion;
/*
练习:使用递归计算1 ~ n的和
分析:
递归就是方法自己调用自己,必须定义一个求和方法,自己调用自己求和
公式:1-n的和就相当于n-1的和
n+(n-1)+(n-2)+(n-3)+...+1
5+(5-1)+(4-1)+...+1
已知:
n:传递过来 10,100,1000
1:加到1结束
未知:
n-1
递归的目的:获取下一个被加的数字n-1
递归的结束的条件:获取到1的时候结束
*/
public class Demo02DiGui {
public static void main(String[] args) {
int sum = getSum(100);
System.out.println(sum);
}
/*
定义一个求和方法,自己调用自己求和
*/
public static int getSum(int n){//5,4,3,2,1
//递归的结束的条件:获取到1的时候结束
if(n==1){
return 1;
}
//递归的目的:获取下一个被加的数字n-1
return n + getSum(n-1);
}
}
3.练习:递归求阶乘(重点)
package com.itheima.demo02Recursion;
/*
练习:递归求阶乘(重点)
演示和求和的不同即可
分析:
递归就是方法自己调用自己,必须定义一个求阶乘方法,自己调用自己求阶乘
公式:1-n的和就相当于n-1的和
5的阶乘5!=5*4*3*2*1;
n的阶乘n!=n*(n-1)*(n-2)*(n-3)*...1;
已知:
n:传递过来 5,10...
1:乘到1结束
未知:
n-1
递归的目的:获取下一个被乘的数字n-1
递归的结束的条件:获取到1的时候结束
*/
public class Demo03DiGUi {
public static void main(String[] args) {
int jc = jieCheng(5);
System.out.println(jc);
}
/*
定义一个计算阶乘的方法,方法自己调用自己
*/
public static int jieCheng(int n){//5,4,3,2,1
//递归的结束的条件:获取到1的时候结束
if(n==1){
return 1;
}
//递归的目的:获取下一个被乘的数字n-1
return n * jieCheng(n-1);
}
}
5.练习:文件搜索
package com.itheima.demo02Recursion;
import java.io.File;
/*
练习:文件搜索
模拟windows系统中的文件搜索功能
搜索出d:\aaa目录中的所有.java文件结尾的文件,并打印文件的绝对路径
分析:
1. 目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。
2. 遍历目录时,获取的子文件,通过文件名称,判断是否符合递归条件。
3. 是目录则继续递归遍历,是文件的输出.java结尾的文件
步骤:
1.定义一个根据目录遍历目录的方法getAllFile,参数传递要遍历目录的File对象
2.在方法中根据参数传递要遍历的目录,遍历目录
3.获取每一个文件|文件夹的File对象
4.判断File对象是一个文件时候文件夹
是一个文件:判断文件是否以.java|.JAVA结尾,是则打印文件的绝对路径
是一个文件夹:继续遍历文件夹
我们发现getAllFile就是一个遍历目录的方法,调用getAllFile方法即可(递归)
*/
public class Demo04Test {
public static void main(String[] args) {
File file = new File("d:\\aaa");
getAllFile(file);
}
/*
1.定义一个根据目录遍历目录的方法getAllFile,参数传递要遍历目录的File对象
*/
public static void getAllFile(File dir){
//2.在方法中根据参数传递要遍历的目录,遍历目录
File[] files = dir.listFiles();
//增加一个非空判断,防止空指针异常
if(files!=null && files.length>0){
//3.获取每一个文件|文件夹的File对象
for (File f : files) {
//4.判断File对象是一个文件时候文件夹
if(f.isFile()){
//是一个文件:判断文件是否以.java|.JAVA结尾,是则打印文件的绝对路径
/*
把File对象转换为字符串
String f.toString(); "D:\aaa\aaa.java"
String f.getPath(); "D:\aaa\aaa.java"
String f.getName(); "aaa.java"
B.JAVA==>变成小写的==>toLowerCase()==>"b.java"
*/
if(f.getName().toLowerCase().endsWith(".java")){
System.out.println(f.getAbsolutePath());
}
}else{
//是一个文件夹:继续遍历文件夹
//我们发现getAllFile就是一个遍历目录的方法,调用getAllFile方法即可(递归)
getAllFile(f);
}
}
}
}
}
第三章 IO概述
1.IO流的概述和分类
2.一切皆为字节
硬盘中的一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存(计算机只能识别0和1),都一个一个的字节(1个字节=8比特位),那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据(1,0)。
0,1比特位:计算机的最小单位
为了方便把8个0,1组成一个字节:计算机的基本单位
第四章 字节流
1.字节输出流的介绍(了解)
java.io.OutputStream类:字节输出流
此抽象类是表示输出字节流的所有类的超类。
OutputStream类是所有字节输出流的父类,里边定义了所有字节输出流共性成员方法,任意的子类都可以使用
OutputStream类中定义的共性成员方法:
public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,
从偏移量 off开始输出到此输出流。
public abstract void write(int b) :将指定的字节输出流
-------------------------------------------------------------------------------------
java.io.FileOutputStream:文件字节输出流 extends OutputStream:字节输出流
作用:把内存中数据以字节的方式写入到文件中
构造方法:
FileOutputStream(File file) 创建FileOutputStream对象
FileOutputStream(String name) 创建FileOutputStream对象
参数:传递写入数据的目的地 d:\\1.txt
File file:目的地就是一个文件
String name:目的地就是一个文件的路径
构造方法的作用:
1.创建FileOutputStream对象
2.会根据传递写入数据的目的地,创建一个相关的文件
3.会把FileOutputStream对象指向创建好的文件
-------------------------------------------------------------------------------------
java程序把数据由内存中写入到硬盘中底层步骤:
java程序==>JVM==>操作系统==>调用操作系统中写数据的方法==>把数据写入到文件中
2.字节输出流的基本使用(重点)
package com.itheima.demo03OutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
字节输出流的基本使用(重点)
使用步骤:
1.创建文件字节输出流FileOutputStream对象,构造方法中绑定要写入的目的地
2.使用FileOutputStream对象中的方法write,把数据以字节的方式写入到文件中
3.释放资源(关闭此输出流并释放与此流相关联的任何系统资源)
*/
public class Demo01FileOutputStream {
public static void main(String[] args) throws IOException {
//1.创建文件字节输出流FileOutputStream对象,构造方法中绑定要写入的目的地
//FileOutputStream fos = new FileOutputStream("e:\\1.txt");//FileNotFoundException: e:\1.txt (系统找不到指定的路径。)
FileOutputStream fos = new FileOutputStream("day10\\1.txt");
//2.使用FileOutputStream对象中的方法write,把数据以字节的方式写入到文件中
//void write(int b) 一次写一个字节
fos.write(97);
//3.释放资源(关闭此输出流并释放与此流相关联的任何系统资源)
fos.close();
}
}
2.使用记事本打开文件会查询编码表(扩展-面试)
3.字节输出流中写多个字节的方法(重点)
package com.itheima.demo03OutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
字节输出流中写多个字节的方法(重点)
void write(int b) 一次写一个字节
void write(byte[] b) 一次写数组中的多个字节
void write(byte[] b, int off, int len) 一次写数组中的一部分字节
int off:数组的开始索引 int len:写的个数
*/
public class Demo02FileOutputStream {
public static void main(String[] args) throws IOException {
//需求:把65,66,67这三个字节写入到文件中
FileOutputStream fos = new FileOutputStream("day10\\2.txt");
//一次写一个字节,写三次
//fos.write(65);
//fos.write(66);
//fos.write(67);
byte[] bytes = {65,66,67};
//一次把数组中的所有字节写入到文件中
fos.write(bytes);
fos.close();
byte[] bytes2 = {字节数组的数据,参考资料中的文件};
FileOutputStream fos2 = new FileOutputStream("day10\\1.jpg");
//把字节数组中所有字节写入到文件中,注意文件的后缀使用.jpg
fos2.write(bytes2);
fos2.close();
FileOutputStream fos3 = new FileOutputStream("day10\\2.jpg");
//把字节数组中的一部分字节写入到文件中,注意文件的后缀使用.jpg
fos3.write(bytes2,0,2000);
fos3.close();
}
}
4.字节输出流的续写和换行(重点)
package com.itheima.demo03OutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
续写:追加写
使用两个参数的构造方法:
FileOutputStream(File file, boolean append)
FileOutputStream(String name, boolean append)
参数:
File file|String name:写入数据的目的地
boolean append:追加写开关
true:可以续写(在之前的文件末尾接着写数据)
false:不可以续写(创建一个新的空白文件,把之前同名的文件覆盖了,在新文件中写数据)
*/
public class Demo03FileOutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream(new File("day10\\3.txt"),true);
byte[] bytes = "你好".getBytes();
fos.write(bytes);
fos.close();
}
}
package com.itheima.demo03OutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
/*
换行:使用换行符号
Windows系统里,每行结尾是 回车+换行 ,即\r\n;
Unix系统里,每行结尾只有 换行 ,即\n;
Mac系统里,每行结尾是 回车 ,即\r。从 Mac OS X开始与Linux统一。
*/
public class Demo04FileOutputStream {
public static void main(String[] args) throws IOException {
//需求: 已知集合中存储了一些数据,我们想把集合中的数据写入到文件中保存每个数据写一行,如何实现那?
ArrayList<String> list = new ArrayList<>();
list.add("i love java!");
list.add("i need java!");
list.add("i miss java!");
FileOutputStream fos = new FileOutputStream("day10\\4.txt",true);
//遍历集合获取每一个元素
for (String s : list) {
fos.write(s.getBytes());
//每写完一个元素,写一个回车换行符号
fos.write("\r\n".getBytes());
}
fos.close();
}
}
5.字节输入流的介绍(了解)
java.io.InputStream:字节输入流
此抽象类是表示字节输入流的所有类的超类。
InputStream是所有字节输入流的父类,里边定义所有字节输入流*性的成员方法,任意的字节输入流都可以使用
共性的成员方法:
int read() 一次读文件中的一个字节并返回
int read(byte[] b) 一次读取文件中的多个字节存储到数组中
void close() 关闭此输入流并释放与该流关联的所有系统资源。
java.io.FileInputStream:文件字节输入流 extends InputStream:字节输入流
作用:可以把文件中的数据,以字节的方式读取到内存中
构造方法:
FileInputStream(File file) 创建FileInputStream对象
FileInputStream(String name) 创建FileInputStream对象
参数:传递要读取的数据源
File file:数据源就是一个文件
String name:数据源是一个文件路径
构造方法的作用:
1.创建FileInputStream对象
2.会把创建FileInputStream对象指向要读取文件的第一个字节
注意:如果传递的文件|文件路径不存在,那么创建流对象会抛出文件找不到异常
使用java程序读取文件的底层过程:
java程序==>JVM==>操作系统==>调用操作系统读取文件的方法==>把数据读取到内存中
6.字节输入流的基本使用:一次读取一个字节(重点)
package com.itheima.demo04InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
字节输入流的基本使用:一次读取一个字节(重点)
int read() 一次读取文件中的一个字节并返回
使用步骤:
1.创建文件字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
2.使用FileInputStream对象中的方法read,以字节的方式读取文件
3.释放资源
*/
public class Demo01FileInputStream {
public static void main(String[] args) throws IOException {
//1.创建文件字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("day10\\a.txt");
//2.使用FileInputStream对象中的方法read,以字节的方式读取文件
/*
我们发现,使用read方法读取文件是一个重复的过程
可以使用循环简化读取的代码,不知道文件中有多少字节,也不知道循环要循环多少次
使用while循环,循环的结束条件,read方法返回-1结束
while循环布尔表达式的含义: (len=fis.read())!=-1
1.fis.read() 读取文件中的一个字节
2.len=fis.read() 把读取到的字节赋值给变量len
3.(len=fis.read())!=-1 判断变量len是否为-1
不是-1,执行循环体,打印len(读取到的字节)
是-1,结束循环
*/
int len = 0;
while ((len=fis.read())!=-1){
System.out.print((char)len);
}
//3.释放资源
fis.close();
}
/*
int len = fis.read();
System.out.println(len);//97
len = fis.read();
System.out.println(len);//98
len = fis.read();
System.out.println(len);//99
len = fis.read();
System.out.println(len);//-1
*/
}
重点代码:
package com.itheima.demo04InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
字节输入流的基本使用:一次读取一个字节(重点)
int read() 一次读取文件中的一个字节并返回
使用步骤:
1.创建文件字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
2.使用FileInputStream对象中的方法read,以字节的方式读取文件
3.释放资源
*/
public class Demo01FileInputStream {
public static void main(String[] args) throws IOException {
//1.创建文件字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("day10\\a.txt");
//2.使用FileInputStream对象中的方法read,以字节的方式读取文件
int len = 0;
while ((len=fis.read())!=-1){
System.out.print((char)len);
}
//3.释放资源
fis.close();
}
}
7.使用字节输入流一次读取多个字节(重点)
package com.itheima.demo04InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
/*
使用字节输入流一次读取多个字节(重点)
int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
明确两件事情:
1.方法的参数字节数组byte[]的作用是什么?
存储读取到的多个字节
长度使用多少合适:一般都使用1024 或者 1024的整数倍
1个字节=8个比特位(0,1)
1k=1024字节
1M=1024k
1G=1024M
1T=1024G
1P=1024T
2.方法的返回值int是什么?
每次读取的有效字节个数
读取到结尾返回-1
String类的构造方法:
String(byte[] bytes) 把字节数组查询编码表转换为字符串
String(byte[] bytes, int offset, int length) 把字节数组的一部分查询编码表转换为字符串
int offset:开始索引 int length:转换个数
*/
public class Demo02FileInputStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("day10\\b.txt");
/*
我们又发现了,使用read(byte[])方法,读取文件也是一个重复的过程
可以使用循环优化,不知道文件中有多少字节,使用while循环
while循环结束的条件,read返回-1
*/
int len = 0;
byte[] bytes = new byte[1024];
while ((len=fis.read(bytes))!=-1){
//System.out.println(Arrays.toString(bytes));//[65, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0,...]
//把读取到有效字节转换为字符串
System.out.println(new String(bytes,0,len));
}
fis.close();
}
/*
byte[] bytes = new byte[2];
System.out.println(Arrays.toString(bytes));//[0, 0]
int len = fis.read(bytes);
System.out.println(len);//2
System.out.println(Arrays.toString(bytes));//[65, 66]
System.out.println(new String(bytes));//AB
len = fis.read(bytes);
System.out.println(len);//2
System.out.println(new String(bytes));//CD
len = fis.read(bytes);
System.out.println(len);//1
System.out.println(new String(bytes));//ED
len = fis.read(bytes);
System.out.println(len);//-1
System.out.println(new String(bytes));//ED
*/
}
重点代码:
package com.itheima.demo04InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
/*
使用字节输入流一次读取多个字节(重点)
int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
明确两件事情:
1.方法的参数字节数组byte[]的作用是什么?
存储读取到的多个字节
长度使用多少合适:一般都使用1024 或者 1024的整数倍
1个字节=8个比特位(0,1)
1k=1024字节
1M=1024k
1G=1024M
1T=1024G
1P=1024T
2.方法的返回值int是什么?
每次读取的有效字节个数
读取到结尾返回-1
String类的构造方法:
String(byte[] bytes) 把字节数组查询编码表转换为字符串
String(byte[] bytes, int offset, int length) 把字节数组的一部分查询编码表转换为字符串
int offset:开始索引 int length:转换个数
*/
public class Demo02FileInputStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("day10\\b.txt");
int len = 0;
byte[] bytes = new byte[1024];
while ((len=fis.read(bytes))!=-1){
//把读取到有效字节转换为字符串
System.out.println(new String(bytes,0,len));
}
fis.close();
}
}
package com.itheima.demo04InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
/*
使用字节输入流读取图片
day10\\1.jpg
8,528 字节
*/
public class Demo03FileInputStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("day10\\1.jpg");
byte[] bytes = new byte[8528];
int len = 0;
while ((len=fis.read(bytes))!=-1){
System.out.println(Arrays.toString(bytes));
}
fis.close();
}
}
注意:new String的时候不要导包,默认的第一个不是lang包中的String
8.文件复制(重点)
原理:
代码实现:
package com.itheima.demo05copyFile;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
文件的复制:一读一写
1.创建文件字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
2.创建文件字节输出流FileOutputStream对象,构造方法中绑定要写入的目的地
3.使用FileInputStream对象中的方法read,以字节的方式读取文件
4.使用FileOutputStream对象中的方法write,把读取到字节写入到目的地
5.释放资源(先开的后关)
*/
public class Demo01CopyFile {
public static void main(String[] args) throws IOException {
long s = System.currentTimeMillis();
//copyFile01();
copyFile02();
long e = System.currentTimeMillis();
System.out.println("复制文件共耗时:"+(e-s)+"毫秒");
}
/*
使用字节输入流一次读取多个字节,使用字节输出流一次写多个字节复制文件
c:\\全球通史.txt 4.91 MB (5,155,785 字节) 复制文件共耗时:65毫秒
c:\\缘起.mp4 64.8 MB (67,995,218 字节) 复制文件共耗时:974毫秒
c:\\748m.rar 748 MB (785,042,177 字节) 复制文件共耗时:1537毫秒
*/
private static void copyFile02() throws IOException {
//1.创建文件字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("c:\\748m.rar");
//2.创建文件字节输出流FileOutputStream对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("d:\\748m.rar");
//3.使用FileInputStream对象中的方法read,以字节的方式读取文件
byte[] bytes = new byte[1024*500];
int len = 0;
while ((len=fis.read(bytes))!=-1){
//4.使用FileOutputStream对象中的方法write,把读取到字节写入到目的地
fos.write(bytes,0,len);//每次写读取到的有效字节,最后一次读取不一定是1024个
}
//5.释放资源(先开的后关)
fos.close();
fis.close();
}
/*
使用字节输入流一次读取一个字节,使用字节输出流一次写一个字节复制文件
c:\\1.jpg 157 KB (161,548 字节) 复制文件共耗时:1823毫秒
c:\\全球通史.txt 4.91 MB (5,155,785 字节) 复制文件共耗时:36184毫秒
*/
private static void copyFile01() throws IOException {
//1.创建文件字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("c:\\全球通史.txt");
//2.创建文件字节输出流FileOutputStream对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("d:\\全球通史.txt");
//3.使用FileInputStream对象中的方法read,以字节的方式读取文件
int len = 0;
while ((len=fis.read())!=-1){
//4.使用FileOutputStream对象中的方法write,把读取到字节写入到目的地
fos.write(len);
}
//5.释放资源(先开的后关)
fos.close();
fis.close();
}
}
注意:流对象的参数只能是文件,不能是文件夹
经验值分享
1.已知的文件复制代码
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test_文件复制 {
public static void main(String[] args) throws IOException {
//创建输入流
FileInputStream fis = new FileInputStream("day13\\123.jpg");
//创建输出流
FileOutputStream fos = new FileOutputStream("day13\\复制.jpg");
//一次读取多个字节
byte[] bytes = new byte[1024];
int len;
while((len=fis.read(bytes)) != -1){
//一次写出多个字节
fos.write(len);
}
//关流
fos.close();
fis.close();
}
}
2.出现的问题
源文件“123.jpg”的大小:
目标文件“复制.jpg”的大小:
3.问题的分析
read()方法每次读取1024个字节存放在数组中,返回的是实际读取到的字节个数len(一个整数)。
在write()输出方法中,写的是len,也就是说每次输出的是一个整数。
源文件共13465字节,需要循环读取14次,所以如上代码写出到文件中的是14个字节。并没有输出实际读取
到的数组内容,所以文件复制错误。
4.问题的解决办法
在输出数据时应该写的是:
fos.write(bytes,0,len);
bytes中存放的是读取到的字节内容, 0 代表从数组的0索引开始输出,len代表本次输出的字节个数。
总结:
数组是文件复制时字节的容器,读取时把字节读取到数组中,并记录读取到的字节个数,输出时把数组中指定个数的字节输出,最终完成文件的复制。