由浅到深认识Java语言(37):I/O流

该文章Github地址:https://github.com/AntonyCheng/java-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】

在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】& CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!

上一章:由浅到深认识Java语言(36):I/O流

44.I/O流(操作文件中的数据)

字符流

只能操作文本文件;

字符流 = 字节流 + 编码表

Writer类

是所有字符输出流的超类(写入文本文件);

  • write(int c) 写入单个字符;
  • write(char[] ch) 写入字符数组;
  • write(char[] ch,int off,int len) 写入字符数组一部分,开始索引以及写入的个数;
  • write(String str) 写入字符串;
  • flush() 刷新该流的缓冲(该类写入数据时先写入内存,只能刷新了数据才会抵达目的路径),而在 close() 方法完成后也会自动调用一次 flush() 方法,但是建议手动刷新,防止内存积压过多;
OutputStreamWriter 实现类

OutputStreamWriter 实现类继承 Writer 类,是字符的输出流,同时也被称作转换流,这个类也是“装饰者”,装饰输出流(OutputStream);

转换流:把字符流转换成字节流;

构造方法:

  • OutputStreamWriter(OutputStream out) 传递任意字节输出流;
  • OutputStreamWriter(OutputStream out,String 编码表名) 传递任意字节输出流,编码表名,不同的 IDE 有不同的默认编码表,IDEA 是 UTF-8 ,eclipse 是 GBK;

使用类示例如下:

package top.sharehome.Demo;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Demo {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        OutputStreamWriter osw = null;
        try {
            fos = new FileOutputStream("d:\\大学课程学习文档\\java\\Practice\\IO\\test1.txt");
            osw = new OutputStreamWriter(fos, "utf8");
            osw.write("啦啦啦啦啦啦");
            osw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (osw != null) {
                    osw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Reader类

是所有字符输入流的超类(读取文本文件);

  • int read() 读取单个字符;
  • int read(char[] ch) 读取字符数组;
InputStreamReader 实现类

InputStreamWriter 实现类继承 Reader 类,是字符的输入流,同时也被称作转换流,这个类也是“装饰者”,装饰输入流(InputStream);

转换流:字节流转成字符流;

构造方法:

  • InputStreamReader(InputStream in) 传递任意字节输入流;
  • InputStreamReader(InputStream in,String 编码表名) 传递任意字节输入流,编码表名,不同的 IDE 有不同的默认编码表,IDEA 是 UTF-8 ,eclipse 是 GBK;

使用类示例如下:(test2.txt 文件如下)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package top.sharehome.Demo;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Demo {
    public static void main(String[] args) {
        FileInputStream fis = null;
        InputStreamReader isr = null;
        try {
            fis = new FileInputStream("d:\\大学课程学习文档\\java\\Practice\\IO\\test2.txt");
            isr = new InputStreamReader(fis);
            char[] ch = new char[1024];
            int flag = 0;
            while ((flag=isr.read(ch)) != -1) {
                System.out.println(new String(ch, 0, flag));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (isr != null) {
                    isr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

便捷类

  • FileWriter 继承自 OutputStreamWriter;

    • 字符的输出流,写入文本文件;
    • 直接采用默认的编码表(utf-8);
    • FileWriter 构造方法直接传递字符串的文件名即可,该文件若在项目根路径不存在,则在根路径创建后再写入;

    示例如下:

    package top.sharehome.Demo;
    
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Demo {
        public static void main(String[] args) {
            FileWriter fw = null;
            try {
                fw = new FileWriter("d:\\大学课程学习文档\\java\\Practice\\IO\\test2.txt");
                fw.write("你好 IO流");
                fw.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fw != null) {
                        fw.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • FileReader 继承自 InputStreamReader;

    • 字符的输入流,读取文本文件;
    • 直接采用默认的编码表;
    • FileReader 构造方法直接传递字符串的文件名即可,必须要有数据源文件;

    示例如下:

    package top.sharehome.Demo;
    
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Demo {
        public static void main(String[] args) {
            FileReader fr = null;
            try {
                fr = new FileReader("d:\\大学课程学习文档\\java\\Practice\\IO\\test2.txt");
                char[] ch = new char[1024];
                int flag = 0;
                while ((flag = fr.read(ch)) != -1) {
                    System.out.print(new String(ch,0,flag));
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fr != null) {
                        fr.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

字符流的缓冲流

使用字符流的缓冲流,提高原有流对象的读写性能;

字符流的缓冲流是字符流中便捷类的**“装饰者”**;

  • BufferedWriter 继承自 Writer;

    • 字符输出流的缓冲流,写入文本文件;

    • 特殊方法:newLine() 写入文本换行符,由于每个操作系统的换行符不一样,这个方法就实现了代码的跨平台性;

      示例如下:

      package top.sharehome.Demo;
      
      import java.io.BufferedWriter;
      import java.io.FileWriter;
      import java.io.IOException;
      
      public class Demo {
          public static void main(String[] args) {
              FileWriter fr = null;
              BufferedWriter bf = null;
              try {
                  fr = new FileWriter("d:\\大学课程学习文档\\java\\Practice\\IO\\test1.txt");
                  bf = new BufferedWriter(fr);
                  bf.write(97);
                  bf.newLine();
                  bf.write(98);
                  bf.flush();
              }catch (IOException e){
                  e.printStackTrace();
              }finally {
                  try {
                   if (fr!=null){
                       fr.close();
                   }
                  }catch (IOException e){
                      e.printStackTrace();
                  }
              }
          }
      }
      

      打印效果如下:

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • BufferedReader 继承自 Reader;

    • 字符输入流的缓冲流,读取文本文件;
    • 特殊方法:readLine() 读取文本一行,由于每个操作系统的换行符不一样,这个方法就实现了代码的跨平台性,返回 String ,当读取完文件后反 null;

    示例如下:

    package top.sharehome.Demo;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Demo {
        public static void main(String[] args) {
            FileReader fr = null;
            BufferedReader br = null;
            try {
                fr = new FileReader("d:\\大学课程学习文档\\java\\Practice\\IO\\test1.txt");
                br = new BufferedReader(fr);
                String flag = null;
                while ((flag = br.readLine()) != null) {
                    System.out.println("flag = " + flag);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (br != null) {
                        br.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

字符流的缓冲流和字节流的缓冲流使用方法大致相同;

在 Java11 之后可以使用一种更简单的方法来读取一个文件(类似于迭代器的遍历方式),此时要用Scanner类来获取一个文件:

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;

/**
 * @author AntonyCheng
 * @date 2022/8/28 17:32
 */

public class Demo {
    public static void main(String[] args) {
        Scanner in = null;
        try {
            //Scanner(Path source, Charset charset)构造器需要Java10
            //Path接口中Path of(String first, String... more)需要Java11
            in = new Scanner(Path.of("d:\\desktop\\txt.png"), StandardCharsets.UTF_8);
            while (in.hasNextLine()) {
                System.out.println(in.nextLine());
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }
}

BufferedWriter 构造方法

new BufferedWriter(Writer w) 传递字符输出流;

BufferedReader 构造方法

new BufferedReader(Reader r) 传递字符输入流;

禁止使用字符流复制文本文件

这是一个错误的应用,不能保证复制后和源文件是一致的;

打印流

  • PrintStream:字节输出流;

  • PrintWriter:字符输出流;

  • 打印流特性:

    • 打印流负责输出打印,不关心数据源;

    • 方便地打印各种形式数据;

    • 打印流永远不会抛出 IO 异常

    • 具有自动刷新的功能;

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      即添加参数 true ,但是要注意自动刷新必须需要 println 或者 printf 或者 format 进行打印

    • 这些依然是**“装饰者”**,需要再构造方法中引入字节流或者字符流;

打印流示例如下:

  • PrintStream 示例:

    package top.sharehome.Demo;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.PrintStream;
    
    public class Demo {
        public static void main(String[] args) {
            FileOutputStream fos = null;
            PrintStream ps = null;
            try {
                fos = new FileOutputStream("d:\\大学课程学习文档\\java\\Practice\\IO\\test1.txt");
                ps = new PrintStream(fos);
                ps.print("这里写什么就会在文件里写什么!");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (ps != null) {
                    ps.close();
                }
            }
        }
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • PrintWriter 示例:

    package top.sharehome.Demo;
    
    import java.io.*;
    
    public class Demo {
        public static void main(String[] args) {
            FileWriter fw = null;
            PrintWriter pw = null;
            try {
                fw = new FileWriter("d:\\大学课程学习文档\\java\\Practice\\IO\\test1.txt");
                pw = new PrintWriter(fw);
                pw.println("这里写什么就会在文件里写什么!");
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (pw != null) {
                    pw.close();
                }
            }
        }
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基本数据流

  • DataInputStream

    • 基本数据类型读取流;
    • 构造方法传递一个字节输入流;
  • DataOutputStream

    • 基本数据类型写入流;
    • 构造方法传递一个字节输出流;
  • 基本数据流依然是一个**“装饰者”**;

基本数据流示例如下:

package top.sharehome.Demo;

import java.io.*;

public class Demo {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        DataOutputStream dos = null;
        FileInputStream fis = null;
        DataInputStream dis = null;
        try {
            fos = new FileOutputStream("d:\\大学课程学习文档\\java\\Practice\\IO\\test1.txt");
            dos = new DataOutputStream(fos);
            fis = new FileInputStream("d:\\大学课程学习文档\\java\\Practice\\IO\\test1.txt");
            dis = new DataInputStream(fis);
            dos.writeInt(6);
            int i = dis.readInt(); //这里不能使用普通的 read() 方法,需要和写入格式相统一
            System.out.println("i = " + i);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (dos != null) {
                    dos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (dis != null) {
                    dis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们要连续写入读取多个值呢?首先想到的是循环,但是循环条件成了一个问题,因为这里传输的是基本数据类型,返回 -1 是有可能的,所以这里只能通过抓取异常来来确定循环结束点;

示例如下:

package top.sharehome.Demo;

import java.io.*;

public class Demo {
    public static void main(String[] args) {
        FileInputStream fis = null;
        DataInputStream dis = null;
        try {
            fis = new FileInputStream("d:\\大学课程学习文档\\java\\Practice\\IO\\test1.txt");
            dis = new DataInputStream(fis);
            while (true){
                try {
                    int readInt = dis.readInt();
                    System.out.println("readInt = " + readInt);
                }catch (IOException e){
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (dis != null) {
                    dis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下一章:由浅到深认识Java语言(38):I/O流

  • 22
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值