• 字符流Reader和Writer


    字符流

    Reader

    输入流:把数据(键盘输入、鼠标、扫描仪等等外设设备)读入到内存(程序)中

    输出流:把内存(程序)中的数据输出到外设或其他地方,从文件角度简单总结就是,输入流就是读数据,输出流就是写数据。

    Reader:输入流、继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符16位

    Writer:输出流、继承自Writer的流都是程序用于向外输出数据的,且数据单位都是字符(16位)

    Reader是Java的IO库提供的另一个输入流接口。和InputStream的区别是,InputStream是一个字节流,即以byte为单位读取,而Reader是一个字符流,即以char为单位读取

    InputStreamReader
    字节流,以byte为单位字符流,以char为单位
    读取字节(-1,0~255):int read()读取字符(-1,0~65535):int read()
    读到字节数组:int read(byte[] b)读到字符数组:int read(char[] c)

    java.io.Reader是所有字符输入流的超类,它最主要的方法是:

    public int read() throws IOException;
    
    • 1

    FileReader

    FileReaderReader的一个子类,它可以打开文件并获取Reader。下面的代码演示了如何完整地读取一个FileReader的所有字符

    public void readFile() throws IOException {
        // 创建一个FileReader对象:
        Reader reader = new FileReader("src/readme.txt"); // 字符编码是???
        for (;;) {
            int n = reader.read(); // 反复调用read()方法,直到返回-1
            if (n == -1) {
                break;
            }
            System.out.println((char)n); // 打印char
        }
        reader.close(); // 关闭流
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    如果文件中包含中文,就会出现乱码,因为FileReader默认的编码与系统相关

    Windows系统的默认编码可能是GBK,打开一个UTF-8编码的文本文件就会出现乱码。

    要避免乱码问题,我们需要在创建FileReader时指定编码:

    Reader reader = new FileReader("src/readme.txt", StandardCharsets.UTF_8);
    
    • 1

    InputStream类似,Reader也是一种资源,需要保证出错的时候也能正确关闭,所以我们需要用try (resource)来保证Reader在无论有没有IO错误的时候都能够正确地关闭:

    try (Reader reader = new FileReader("src/readme.txt", StandardCharsets.UTF_8) {
        // TODO
    }
    
    • 1
    • 2
    • 3

    我们可以先设置一个缓冲区,然后,每次尽可能地填充缓冲区:

    public void readFile() throws IOException {
        try (Reader reader = new FileReader("src/readme.txt", StandardCharsets.UTF_8)) {
            char[] buffer = new char[1000];
            int n;
            while ((n = reader.read(buffer)) != -1) {
                System.out.println("read " + n + " chars.");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    CharArrayReader

    CharArrayReader可以在内存中模拟一个Reader,它的作用实际上是把一个char[]数组变成一个Reader,这和ByteArrayInputStream非常类似:

    try (Reader reader = new CharArrayReader("Hello".toCharArray())) {
    }
    
    • 1
    • 2

    Reader定义了所有字符输入流的超类:

    • FileReader实现了文件字符流输入,使用时需要指定编码;
    • CharArrayReaderStringReader可以在内存中模拟一个字符流输入。

    Reader是基于InputStream构造的:可以通过InputStreamReader在指定编码的同时将任何InputStream转换为Reader

    总是使用try (resource)保证Reader正确关闭。

    Writer

    Reader是带编码转换器的InputStream,它把byte转换为char,而Writer就是带编码转换器的OutputStream,它把char转换为byte并输出。

    WriterOutputStream的区别如下:

    OutputStreamWriter
    字节流,以byte为单位字符流,以char为单位
    写入字节(0~255):void write(int b)写入字符(0~65535):void write(int c)
    写入字节数组:void write(byte[] b)写入字符数组:void write(char[] c)
    无对应方法写入String:void write(String s)

    Writer是所有字符输出流的超类,它提供的方法主要有:

    • 写入一个字符(0~65535):void write(int c)
    • 写入字符数组的所有字符:void write(char[] c)
    • 写入String表示的所有字符:void write(String s)

    FileWriter

    FileWriter就是向文件中写入字符流的Writer。它的使用方法和FileReader类似:

    try (Writer writer = new FileWriter("readme.txt", StandardCharsets.UTF_8)) {
        writer.write('H'); // 写入单个字符
        writer.write("Hello".toCharArray()); // 写入char[]
        writer.write("Hello"); // 写入String
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    CharArrayWriter

    CharArrayWriter可以在内存中创建一个Writer,它的作用实际上是构造一个缓冲区,可以写入char,最后得到写入的char[]数组,这和ByteArrayOutputStream非常类似:

    try (CharArrayWriter writer = new CharArrayWriter()) {
        writer.write(65);
        writer.write(66);
        writer.write(67);
        char[] data = writer.toCharArray(); // { 'A', 'B', 'C' }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    StringWriter

    StringWriter也是一个基于内存的Writer,它和CharArrayWriter类似。实际上,StringWriter在内部维护了一个StringBuffer,并对外提供了Writer接口。

    OutputStreamWriter

    除了CharArrayWriterStringWriter外,普通的Writer实际上是基于OutputStream构造的,它接收char,然后在内部自动转换成一个或多个byte,并写入OutputStream。因此,OutputStreamWriter就是一个将任意的OutputStream转换为Writer的转换器:

    try (Writer writer = new OutputStreamWriter(new FileOutputStream("readme.txt"), "UTF-8")) {
        // TODO:
    }
    
    • 1
    • 2
    • 3

    Writer定义了所有字符输出流的超类:

    • FileWriter实现了文件字符流输出;
    • CharArrayWriterStringWriter在内存中模拟一个字符流输出。

    使用try (resource)保证Writer正确关闭。

    Writer是基于OutputStream构造的,可以通过OutputStreamWriterOutputStream转换为Writer,转换时需要指定编码。

  • 相关阅读:
    C++模板
    谷歌收录工具有什么好用的?
    Python钢筋混凝土结构计算.pdf-已知弯矩确定混凝土梁截面尺寸
    xlua源码分析(三)C#访问lua的映射
    Qt自定义日志输出
    海外问卷调查是不是真的能赚钱?
    浅谈系统稳定性与高可用保障的几种思路
    介绍一个.Net远程日志组件
    2020年12月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试
    Golang http 请求如何设置代理
  • 原文地址:https://blog.csdn.net/m0_59138290/article/details/128007858