当前位置: 首页 > 工具软件 > Reader > 使用案例 >

Java的Reader和Writer

武向文
2023-12-01

Reader

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;

这个方法读取字符流的下一个字符,并返回字符表示的 int ,范围是 0~65535。如果已读到末尾,返回 -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(); 	// 关闭流
}

如果我们读取一个纯 ASCII 编码的文本文件,上述代码工作是没有问题的。但如果文件中包含中文,就会出现乱码,因为 FileReader 默认的编码与系统相关,例如,Windows系统的默认编码可能是 GBK ,打开一个 UTF-8 编码的文本文件就会出现乱码。

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

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

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

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

Reader 还提供了一次性读取若干字符并填充到 char[]数组 的方法:

public int read(char[] c) throws IOException

它返回实际读入的字符个数,最大不超过 char[] 数组的长度。返回 -1 表示流结束。

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

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.");
        }
    }
}

StringReader

StringReader 可以直接把 String 作为数据源:

try (Reader reader = new StringReader("Hello")) {
}

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
}

StringWriter

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

 类似资料: