从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • JavaSE

    • 我的 Java 学习路线
    • 安装 Java
    • Java数据类型

    • Java 多版本配置
    • 面向对象

    • Java核心类

    • IO

      • IO 介绍
      • File 对象介绍
      • InputStream
      • OutputStream
      • Decorator 模式
      • 读写 zip 文件
      • Properties 类
      • 读取 classpath 中的配置文件
      • 序列化与反序列化
      • Reader
        • Read 方法
        • FileReader
        • 读入多个字符
        • CharArrayReader
        • StringReader
        • InputStreamReader
        • 编码问题
        • 小结
      • Writer
      • PrintStream 和 PrintWriter
      • Scanner
      • 使用 Files
      • Console
      • IO 系列小结
    • Java与时间

    • 异常处理

    • 哈希和加密算法

    • Java8新特性

    • 网络编程

  • JavaSenior

  • JavaEE

  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java
  • JavaSE
  • IO
2023-02-02
目录

Reader

# Reader

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

# Read 方法

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

public int read() throws IOException;
1

这个方法读取字符流的下一个字符,并返回字符表示的 int,范围是 0~65535。如果已读到末尾,返回 -1。

# FileReader

FileReader 是 Reader 的一个子类,它可以打开文件并获取 Reader。我们来实践下,读取一个 txt 文件并打印。

我们先新建一个 txt 文件,里面写一些英文(注意先不用中文,可能有编码问题)

然后我们编写代码读取和打印:

import java.io.FileReader

public class IODemo11Reader {
  public static void main(String[] args) throws Exception{
  
    FileReader reader = new FileReader("readme.txt");

    int n = reader.read();
    while(-1 != n){
      System.out.println((char)n);
      n = reader.read();
    }

    reader.close();
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

运行结果:

$ javac IODemo12Writer.java -encoding utf8
$ java IODemo12Writer -encoding utf8  
Hello
1
2
3

# 读入多个字符

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

public int read(char[] c) throws IOException
1

它返回实际读入的字符个数,最大不超过 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.");
        }
    }
}
1
2
3
4
5
6
7
8
9

# CharArrayReader

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

Reader reader = new CharArrayReader("Hello".toCharArray()))
1

# StringReader

StringReader 可以直接把 String 作为数据源,它和 CharArrayReader 几乎一样:

Reader reader = new StringReader("Hello")) 
1

# InputStreamReader

Reader 和 InputStream 有什么关系?

除了特殊的 CharArrayReader 和 StringReader,普通的 Reader 实际上是基于 InputStream 构造的,因为 Reader 需要从 InputStream 中读入字节流(byte),然后,根据编码设置,再转换为 char 就可以实现字符流。如果我们查看 FileReader 的源码,它在内部实际上持有一个 FileInputStream。

既然 Reader 本质上是一个基于 InputStream 的 byte 到 char 的转换器,那么,如果我们已经有一个 InputStream,想把它转换为 Reader,是完全可行的。InputStreamReader 就是这样一个转换器,它可以把任何 InputStream 转换为 Reader。示例代码如下:

// 持有InputStream:
InputStream input = new FileInputStream("src/readme.txt");
// 变换为Reader:
Reader reader = new InputStreamReader(input, "UTF-8");
1
2
3
4

构造 InputStreamReader 时,我们需要传入 InputStream,还需要指定编码,就可以得到一个 Reader 对象。

上述代码实际上就是 FileReader 的一种实现方式。

使用 try (resource) 结构时,当我们关闭 Reader 时,它会在内部自动调用 InputStream 的 close() 方法,所以,只需要关闭最外层的 Reader 对象即可。

# 编码问题

FileReader 默认的编码与系统相关,例如,Windows 系统的默认编码可能是 GBK,打开一个 UTF-8 编码的文本文件就会出现乱码。要避免乱码问题,我们需要在创建的时候指定编码:

    FileInputStream fis = new FileInputStream("readme.txt");
    InputStreamReader  reader = new InputStreamReader(fis,"UTF-8");
1
2

从 JDK11 开始,FileReader 新增加了几个构造方法,可以在创建的时候指定编码:

public FileReader(String fileName, Charset charset) throws IOException
1

# 小结

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

  • FileReader 实现了文件字符流输出;
  • CharReader 和 StringReader 在内存中模拟一个字符流输出。

Reader 是基于 InputStream 构造的,可以通过 InputStreamReader 将 InputStream 转换为 Reader,转换时需要指定编码。

上次更新: 2024/10/1 15:49:31
序列化与反序列化
Writer

← 序列化与反序列化 Writer→

最近更新
01
2025 年 4 月记
04-30
02
山西大同 “订婚强奸案” 将会给整个社会带来的影响有多严重? - 知乎 转载
04-26
03
一个小技巧,让电子书阅读体验翻倍!
04-18
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式