- 能够说出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.释放资源
java.io.File类 文件和目录路径名的抽象表示形式。 把计算机中的文件和文件夹(目录)封装为了File对象,就可以使用File对象来操作这些文件和文件夹 我们可以使用File对象创建文件和文件夹 我们可以使用File对象删除文件和文件夹 我们可以使用File对象获取文件和文件夹的路径 我们可以使用File对象获取文件的大小(单位是字节) 我们可以使用File对象遍历文件夹 记住3个相关的单词: 1.file:文件 2.directory:文件夹(目录) 3.path:路径
路径:表示存储文件和文件夹的路径(位置) 分类: 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
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 } }
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 } }
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 } }
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文件夹不存在 } }
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); } } }
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.直接递归 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.StackOverflowError */ private static void b(int i) { System.out.println(i); if(i==20000){ return;//结束方法 } b(++i); } /* 1.递归必须有结束的条件,保证方法自己调用自己能停止下来,否则会抛出栈内存溢出的错误 Exception in thread "main" java.lang.StackOverflowError */ private static void a() { System.out.println("a方法"); a(); } }
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); } }
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); } }
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); } } } } }
硬盘中的一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存(计算机只能识别0和1),都一个一个的字节(1个字节=8比特位),那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据(1,0)。
0,1比特位:计算机的最小单位
为了方便把8个0,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==>操作系统==>调用操作系统中写数据的方法==>把数据写入到文件中
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(); } }
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(); } }
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(); } }
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==>操作系统==>调用操作系统读取文件的方法==>把数据读取到内存中
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(); } }
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
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(); } }
注意:流对象的参数只能是文件,不能是文件夹
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(); } }
源文件“123.jpg”的大小:
目标文件“复制.jpg”的大小:
read()方法每次读取1024个字节存放在数组中,返回的是实际读取到的字节个数len(一个整数)。
在write()输出方法中,写的是len,也就是说每次输出的是一个整数。
源文件共13465字节,需要循环读取14次,所以如上代码写出到文件中的是14个字节。并没有输出实际读取
到的数组内容,所以文件复制错误。
在输出数据时应该写的是:
fos.write(bytes,0,len);
bytes中存放的是读取到的字节内容, 0 代表从数组的0索引开始输出,len代表本次输出的字节个数。
总结:
数组是文件复制时字节的容器,读取时把字节读取到数组中,并记录读取到的字节个数,输出时把数组中指定个数的字节输出,最终完成文件的复制。