IO流

1.1File类概述和构造方法

  • File:它是文件和目录路径名的抽象表示
    • 文件和目录是可以通过File封装成对象的
    • 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的
  • 绝对路径和相对路径
    • 绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如:G:\文件\java.txt
    • 相对路径:必须使用取自其他路径名的信息进行解释。例如:myFile\java.txt
  • 构造方法

    • File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
    • File(String parent,String child):从父路径名字符串和子路径名字符串创建新的File实例
    • File(File parent,Stringn child):从父抽象路径名和子路径名字符串创建新的File实例

      1. public static void main(String[] args) {
      2. //File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
      3. File file = new File("G:\\一些文件\\新建文件夹");
      4. System.out.println(file);
      5. //File(String parent,String child):从父路径名字符串和子路径名字符串创建新的File实例
      6. File file1 = new File("G:\\一些文件","新建文件夹");
      7. System.out.println(file1);
      8. //File(File parent,Stringn child):从父抽象路径名和子路径名字符串创建新的File实例
      9. File file2 = new File("G:\\一些文件");
      10. File file3 = new File(file2,"新建文件夹");
      11. System.out.println(file3);
      12. }
  • File类创建功能

    • public boolean createNewFile():当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件,并返回true,如果文件存在则返回false
    • public boolean mkdir():创建由此抽象路径名命名的目录
    • public boolean mkdirs():创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
  • File类删除功能

    • public boolean delete():删除由此抽象路径名表示的文件或目录
    • 删除目录时,如果目录下还有其他文件,则该目录不能直接删除,要先删除其内容,再删除目录

      1. public static void main(String[] args) throws IOException {
      2. //需求1:在G:\\一些文件\\新建文件夹目录下创建一个文件java.txt
      3. File file = new File("G:\\一些文件\\新建文件夹\\java.txt");
      4. System.out.println(file.createNewFile());
      5. //需求2:在G:\\一些文件\\新建文件夹下创建一个目录JavaSE
      6. File file1 = new File("G:\\一些文件\\新建文件夹\\JavaSE");
      7. System.out.println(file1.mkdir());
      8. //需求3:在G:\\一些文件\\新建文件夹下创建一个多级目录JavaWeb\\html
      9. File file2 = new File("G:\\一些文件\\新建文件夹\\JavaWeb\\html");
      10. System.out.println(file2.mkdirs());
      11. //需求4:在G:\\一些文件\\新建文件夹目录下创建一个文件javase.txt
      12. File file3 = new File("G:\\一些文件\\新建文件夹\\javase.txt");
      13. //这样会导致生成一个名为javase.txt的文件夹
      14. //System.out.println(file3.mkdir());
      15. System.out.println(file3.createNewFile());
      16. //需求5:在G:\\一些文件\\新建文件夹目录下删除javase.txt文件
      17. System.out.println(file3.delete());
      18. //需求6:在G:\\一些文件\\新建文件夹目录下删除javaSE目录
      19. System.out.println(file1.delete());
      20. }
  • File类判断和获取功能

    • public boolean isDirectory():测试此抽象路径名表示的File是否为目录
    • public boolean isFile():测试此抽象路径名表示的File是否为文件
    • public boolean exists():测试此抽象路径名表示的File是否存在
    • public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
    • public String getPath():将此抽象路径名转换为路径名字符串
    • public String getName():返回由此抽象路径名表示的文件或目录的名称
    • public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
    • public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组

      1. public static void main(String[] args) {
      2. File file = new File("G:\\一些文件\\新建文件夹\\java.txt");
      3. //public boolean isDirectory():测试此抽象路径名表示的File是否为目录
      4. System.out.println(file.isDirectory());
      5. //public boolean isFile():测试此抽象路径名表示的File是否为文件
      6. System.out.println(file.isFile());
      7. //public boolean exists():测试此抽象路径名表示的File是否存在
      8. System.out.println(file.exists());
      9. //public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
      10. System.out.println(file.getAbsolutePath());
      11. //public String getPath():将此抽象路径名转换为路径名字符串
      12. System.out.println(file.getPath());
      13. //public String getName():返回由此抽象路径名表示的文件或目录的名称
      14. System.out.println(file.getName());
      15. System.out.println("===========================");
      16. File file1 = new File("G:\\一些文件\\新建文件夹");
      17. //public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
      18. String[] strings = file1.list();
      19. for (String s:strings){
      20. System.out.println(s);
      21. }
      22. //public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组
      23. File[] files = file1.listFiles();
      24. for (File f:files){
      25. System.out.println(f);
      26. }
      27. }

      2.字节流

      一、IO流分类

      1.根据数据的类型分为:【字节流】和【字符流】

      1.【字节流】:以字节为基本单位,读写数据的流

  • 字节输入流:以字节为基本单位,读数据

  • 字节输出流:以字节为基本单位,写出数据

2.【字符流】:以字符为基本单位,读写数据的流

  • 字符输入流:以字符为基本单位,读数据
  • 字符输出流:以字符为基本单位,写出数据

    2.根据数据的流向分为:【输入流】和【输出流】

    1.【输入流】:把数据从 其他存储设备 上【读取】到 内存 中的流

  • 字节输入流:以字节为基本单位,读数据

  • 字符输入流:以字符为基本单位,读数据

2.【输出流】:把数据从 内存 中【写出】到 其他 存储 设备中的流

  • 字节输出流:以字节为基本单位,写出数据
  • 字符输出流:以字符为基本单位,写出数据

    3.IO流的顶层父类

    - 字节输入流:顶层父类:InputStream —> 抽象类 常见子类:FileInputStream
    - 字节输出流:顶层父类:OutputStream —> 抽象类 常见子类:FileOutputStream
    - 字符输入流:顶层父类:Reader —> 抽象类 常见子类:FileReader
    - 字符输出流:顶层父类:Writer —> 抽象类 常见子类:FileWriter

    二、字节输出流OutPutStream

    OutputStream 输出流顶层父类
    java.io.OutputStream抽象类是所有【字节输出流】的父类,用来【写】出字节输出流

    成员方法:

    - public void close():关闭次输出流并释放与此流相关联的任何系统资源
    - close方法,当完成流的操作时,必须调用此方法,释放系统资源,否则数据写入不完整或消失
    - public abstract void write(int b):将指定的字节写入输出流【一个字节一个字节写入到硬盘】
    - public void write(byte b[]):将 b.length字节从指定的字节数组写入到此输出流【以字节数组的形式写入到硬盘】
    - public void write(byte b[],int off, int len):将指定范围的字节数组的字节数据写到此输出流中【将字节数组中某一段字节数据写到硬盘】

    1.写出单个字节数据
    1. // 1.创建字节输出流对象 路径文件必须真实存在
    2. FileOutputStream fos1 = new FileOutputStream("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt");
    3. // 2.写出 单个字节的数据
    4. fos1.write(72);
    5. // 写入的一个字节数据,我们是往文本文档写入字节数据,但是因为是文本类型,需要将字节数据转换成文本数据,文本就是字符
    6. fos1.write(105);
    7. fos1.write(33);
    8. // 3.关闭流,释放资源
    9. fos1.close();
    (运行结束,会在对应的文件中生成对应的字节,代码中写入的数字为ASCII码,每个数字对应一个字母)
    2.写出字节数组数据
    1. //1.创建字节输出流对象 真实存在的路径
    2. FileOutputStream fos1 = new FileOutputStream("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt");
    3. // 2.创建字节数组
    4. byte[] bytes = {97,98,99};
    5. // 3.写出字节数组中的字节数据
    6. fos1.write(bytes);
    7. // 4.关闭流,释放资源
    8. fos1.close();
    (运行结束,会在对应的文件中生成对应的字节,代码中写入的数字为ASCII码,每个数字对应一个字母)
    3.写出指定范围字节数组的数据
    1. // 1.创建字节输出流对象 真实存在的路径
    2. FileOutputStream fos1 = new FileOutputStream("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt");
    3. // 2.创建字节数组
    4. byte[] bytes = {97,98,99};
    5. // 3.写出字节数组中的字节数据
    6. fos1.write(bytes,1,2);
    7. // 4.关闭流,释放资源
    8. fos1.close();
    (运行结束,会在对应的文件中生成对应的字节,代码中写入的数字为ASCII码,每个数字对应一个字母)
    4.数组追加续写
    1. // 1.创建字节输出流对象 真实存在的路径
    2. FileOutputStream fos1 = new FileOutputStream("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt",true);
    3. // 2.创建字节数组
    4. byte[] bytes = {97,98,99,100};
    5. // 3.写出字节数组中的字节数据
    6. fos1.write(bytes,1,2);
    7. // 4.关闭流,释放资源
    8. fos1.close();
    (这里续写是沿着第三个练习续写的,第三个练习写了 “bc”,这里也续写一个“bc”,不续写的话,同一个文件的数据会被覆盖)
    5.写出换行 ```java
    1. /*
    2. * 需求: 写一首诗
    3. * 鹅鹅鹅,
    4. * 曲项向天歌。
    5. * 白毛浮绿水,
    6. * 红掌拨清波。
    7. * */

// 1.创建字节输出流对象,关联到 day12\resources\a.txt 真实存在 FileOutputStream fos1 = new FileOutputStream(“day12_File类与递归&IO流&字符流&字节流\resources\a.txt”); // 2.写出字节数组中的字节数据 fos1.write(“鹅鹅鹅,”.getBytes()); fos1.write(“\r\n”.getBytes()); fos1.write(“曲项向天歌。”.getBytes()); fos1.write(“\r\n”.getBytes()); fos1.write(“白毛浮绿水,”.getBytes()); fos1.write(“\r\n”.getBytes()); fos1.write(“红掌拨清波。”.getBytes()); // 3.关闭流,释放资源 fos1.close();

  1. <a name="LYSNX"></a>
  2. # 三、字节输入流InputStream
  3. **java.io.InputStream 抽象类,给类是所有字节输入流的父类,用于读取字节数据**
  4. <a name="k3h9J"></a>
  5. ### 构造方法:
  6. **概述:java.io.FileInputStream类是InputStream的实现子类,表示字节输入流,用于读取数据**<br />**- public FileInputStream(String name):通过打开与实际文件的连接来创建一个字节输入流对象,该文件由文件系统的路径名 name命名<br />- public FileInputStream(File file):通过打开与实际文件的连接来创建一个字节输入流对象,该文件由文件系统中的文件对象file命名**
  7. <a name="CwK8v"></a>
  8. ### 成员方法:
  9. **- public void close():关闭输入流并释放与此流相关的任何系统资源<br />- public abstract int read():从输入流读取数据的下一个字节,每次读取一个字节<br />- public int read(byte b[]):从输入流读取一些字节数据,并将它们存储到字节数住b中**
  10. **1.构造方法 **
  11. ```java
  12. // 创建字节输入流对象,关联数据源文件路径,真实存在的路径
  13. FileInputStream fileInputStream1 = new FileInputStream("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt");
  14. FileInputStream fileInputStream2 = new FileInputStream(new File("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt"));
  15. // 创建字节输入流对象,关联数据源文件路径,不存在的路径,会报异常:系统找不到指定的文件
  16. FileInputStream fileInputStream3 = new FileInputStream("day12_File类与递归&IO流&字符流&字节流\\resources\\a1.txt");

2.读取单个字节数据


  1. // 创建字节输入流对象,关联数据源文件路径 真实存在的
  2. FileInputStream fileInputStream1 = new FileInputStream("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt");
  3. // 定义一个Int类型的变量,用来存储读取到的数据
  4. int len;
  5. // 使用循环的方式读取数据
  6. while ((len = fileInputStream1.read()) != -1){
  7. // while循环中的条件,fis每读取一个字节,会优先复制给len变量,然后拿len变量与 -1 进行比较
  8. System.out.print((char) len);
  9. }
  10. // 关闭流
  11. fileInputStream1.close();

(输出语句中如果不加 char 强转字符的话,打印出来的就是ASCII码,需要强转成字符类型)

3.读取字节数组长度的字节数据

  1. public static void main (String[] args) throws IOException {
  2. // 创建字节输入流对象,关联数据源文件路径 真实存在的
  3. FileInputStream fileInputStream1 = new FileInputStream("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt");
  4. // 创建byte[] 数组,长度暂定为2,用来存储读取到的字节数据
  5. byte[] bytes = new byte[2];
  6. // 定义一个int类型的变量,用来存储读取到的字节个数
  7. int len;
  8. //while循环的方式来遍历读取本中的数据
  9. while ((len = fileInputStream1.read(bytes)) != -1){
  10. System.out.println(new String(bytes,0,len));
  11. }
  12. // 关闭流
  13. fileInputStream1.close();
  14. /*
  15. * 使用数组读取的话,每次读取多个字节,减少系统之间的IO操作次数,从而提高了读写的效率,建议开发中如此使用
  16. * */
  17. }

(因为数组不能强转,所以用来String的一个方法用来打印数组)
字节流复制文件

  1. public static void main(String[] args) {
  2. try {
  3. // 1、创建一个字节输入流管道与原视频接通
  4. InputStream is = new FileInputStream("file-io-app/src/out04.txt");
  5. // 2、创建一个字节输出流管道与目标文件接通
  6. OutputStream os = new FileOutputStream("file-io-app/src/out05.txt");
  7. // 3、定义一个字节数组转移数据
  8. byte[] buffer = new byte[1024];
  9. int len; // 记录每次读取的字节数。
  10. while ((len = is.read(buffer)) != -1){
  11. os.write(buffer, 0 , len);
  12. }
  13. System.out.println("复制完成了!");
  14. // 4、关闭流。
  15. os.close();
  16. is.close();
  17. } catch (Exception e){
  18. e.printStackTrace();
  19. }
  20. }

四、字符流与字节流的编码转换

由于字节流操作中文不是特别方便,所以Java提供了字符流
字符流 = 字节流 + 编码表
汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数
字符串中的编码解码问题
1.编码:

  • byte[] getBytes():使用平台默认字符集将该String编码为一系列字节,将结果存储到新的字节数
  • 中byte[] getBytes(String charsetName):使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中

2.解码:

  • String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的String
  • String(byte[] bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的String

    五、字符输入流Reader

    java.io.Reader类:抽象类,表示用于读取字符流的所有类的超类,可以读取字符信息到内存中

    构造方法:

    概述:java.io.FileReade类,继承Reader类,表示字符输入流,用来读取字符数据对象
    - public FileReader(String fileName):FileReader类对象,给定要读取的文件的名称
    - public FileReader(File file):FileReader类对象,给定要读取的file文件的名称

    成员方法:

    - public abstract void close():关闭此流并释放与此流相关的任何系统资源
    - public int read():从输入流读取一个字符,读取到末尾返回 -1
    - public int read(char cbuf[]):从输入流中读取一些数据,并将它们存储到字符数组cbuf中

    1.构造方法 ```java // 文件真实存在 FileReader fr1 = new FileReader(“day12_File类与递归&IO流&字符流&字节流\resources\a.txt”);

// 文件不存在,会报出异常 FileReader fr2 = new FileReader(“day12_File类与递归&IO流&字符流&字节流\resources\a.txt”);

  1. **2.读取单个字符数据**
  2. ```java
  3. // 创建字符输入流对象
  4. FileReader fr1 = new FileReader("day12_File类与递归&IO流&字符流&字节流\\resources\\a.txt");
  5. int len;
  6. // 循环读取
  7. while ((len = fr1.read()) != -1){
  8. System.out.print((char) len);
  9. }
  10. //关闭
  11. fr1.close();

3.读取字符的数组长度的字符数据

  1. // 创建字符输入流对象
  2. FileReader fr1 = new FileReader("day12_File类与递归&IO流&字符流和字节流\\resources\\a.txt");
  3. int len;// 每次读取返回的字符数据
  4. char[] chars = new char[1024];
  5. // 循环读取
  6. while( (len = fr1.read(chars)) != -1 ){
  7. System.out.print(new String(chars,0,len));
  8. }
  9. // 关闭流
  10. fr1.close();

六、字符输出流Write

java.io.Writer类,抽象类,用于表示字符输出流的所有类的超类,将指定的字符信息写出到目的地

构造方法:

概述:java.io.FileWriter类 是Writer的子类,表示字符输出流,可以用来写出字符数据
- public FileWriter(String fileName)
- public FileWriter(String fileName, boolean append)
- public FileWriter(File file)
- public FileWriter(File file, boolean append)

注意:
1.当你创建一个字符输出流对象时,必须传入一个文件路径
2.前面2个构造方法,传入的路径,如果没有这个文件,会创建这个文件,如果文件里面有数据,数据会被清空
3.后面2个构造方法,多了一个append的参数,true表示不清空,false默认清空

成员方法:

- public void write(int c)
- public void write(char cbuf[])
- public abstract void write(char cbuf[], int off, int len)
- public void write(String str)
- public void write(String str, int off, int len)
- public abstract void flush()
- public abstract void close()

1.构造方法

  1. FileWriter fw1 = new FileWriter("day12_File类与递归&IO流&字符流和字节流\\resources\\a.txt");
  2. FileWriter fw2 = new FileWriter(new File("day12_File类与递归&IO流&字符流和字节流\\resources\\a.txt"));
  3. FileWriter fw3 = new FileWriter("day12_File类与递归&IO流&字符流和字节流\\resources\\a.txt",true);
  4. FileWriter fw4 = new FileWriter(new File("day12_File类与递归&IO流&字符流和字节流\\resources\\a.txt"),true);

2.写出单个字符

  1. // 第一步:创建字符输出流对象。关联目的地文件路径
  2. FileWriter fw1 = new FileWriter(new File("day12_File类与递归&IO流&字符流&字节流\\resources\\b.txt"));
  3. // 第二步:写入单个字符
  4. fw1.write(97);
  5. // 第三步:关闭流
  6. fw1.close();

3.写出字符串

  1. // 第一步:创建字符输出流对象。关联目的地文件路径
  2. FileWriter fw1 = new FileWriter("day12_File类与递归&IO流&字符流和字节流\\resources\\c.txt");
  3. // 第二步:写出字符串
  4. String str = "我今天心情真美丽\r\n嘿嘿哈哈";
  5. fw1.write(str,3,5);
  6. // 第三步:关闭流
  7. fw1.close();

4.写出字符数组

  1. // 第一步:创建字符输出流对象。关联目的地文件路径
  2. FileWriter fw1 = new FileWriter("day12_File类与递归&IO流&字符流&字节流\\resources\\c.txt");
  3. // 第二步:写出字符数组
  4. char[] chars = {'我','是','一','个','伟','大','的','人'};
  5. fw1.write(chars);
  6. // 第三步:关闭流
  7. fw1.close();

七、流的关闭和刷新

- public abstract void flush():刷新缓冲区,流对象可以继续使用
- public abstract void close():关闭流,释放系统资源,关闭流会顺带刷新缓冲区,关闭之后不可操作