在前几篇文章中一直讲的都是InputStream,这是操作字节流的类,然而我们在程序中往往要从文件等stream中读取字符信息,如果只用InputStream能否读取字符信息呢?当然可以。但是这涉及到了一个编码和解码的问题,传输双方必须才用同一种编码方式才能正确接收,这就导致每次在传输时,传输方需要做这么几件事:

1)将需要传输的字符编码成指定字节

2)传输字节

接收方需要做这么几件事:

1)接收字节

2)将字节解码成对应的字符

我们看一下下面的例子:

我在对应目录有一个文件,这个文件是按照utf-8编码的,现在利用InputStream读取到一个byte数组中,如果我们想要读取到文件的内容,还需要继续转码成utf-8格式的字符串。

输出:

the length of bytes is 16

the content is 你好吗?

从上面的例子中,我们看到只有InputStream就能解决传输字符串的问题了,但是每次都要先读成byte字节,再进行转码,麻烦,能不能直接传字符呢?????

答案是:不能!!!

计算机只认识0和1,也就是byte,只能传输byte。

但是别人的博客都说Reader和Writer神马的能传啊?这是理解角度的不同,我就认为不能传字符,爱咋咋地!

好的,我现在就正式介绍这个“能”传字符的Reader(Writer类似,我就不说了)。

先用一个例子说明,如果我们直接用Reader读取文件,会是怎样的?

输出:the length is 5

char [0] is 你

char [1] is 好

char [2] is 吗

char [3] is ?

char [4] is

the content is 你好吗?

这样一来,是不是清爽了,也就是在你读取文件的时候,使用Reader可以直接指定解码方式,这样就可以直接读字符内容了。关于编码的问题,比较复杂,有兴趣的请参考网上其他内容,比如Java中的char,是两个字节,但是如果你的文件是utf-8,读取字符时可能就会出现问题,因为utf-8的字符是变长的,有的字符是一个字节,有的是两个,有的是三个。

不是说计算机只能传输字节么,为什么这里能直接读取字符了,好,下面我带大家深入剖析一下Reader类。

废话少说,先上类图:

Java几乎为每一个InputStream都设计了一个对应的Reader,比如如果你想直接读取文件里的字符,可以用FileReader来代替FileInputStream。BufferedReader也是一个装饰者模式的reader,接收一个Reader作为参数,从而对Reader提供缓存功能。

但是这众多的Reader中,却有一部分没什么用(个人观点),先从Reader的源码看起:

我这里只列出了Reader的两个灵魂函数,即read()和read(char cbuf[], int off, int len)

read()和InputStream中的read()相似,不过这里是只读取一个字符,而这个方法通过调用read(char cbuf[], int off, int len) 来实现,这个方法是抽象方法,Reader的子类通过实现这个方法达到读取不同介质的目的。

接下来就说说这个Reader家族中最重要的实现类,InputStreamReader类。

先看看这个类的结构:

接着还是先放部分代码上来。

从上面的代码可以看出,InputStreamReader有一个重要的域,就是这个

private finalStreamDecoder sd;

就是这个域帮助InputStreamReader解决了编码的问题。其实这个StreamDecoder 类也是Reader的子类,从后面的read()方法也能看出,InputStreamReader的read()其实就是这个sd的read()方法,在剖析StreamDecoder 之前,我们再看一眼InputStreamReader的构造方法。

InputStreamReader有四个构造函数,我这里只说前两个,第一个接收一个InputStream作为参数。第二个多了一个charsetName,这就是指定了编码方式,第一种为什么不指定?如果不指定就采用系统默认的编码方式。这在后面的StreamDecode的源码中马上就能看出来。

现在我们再看看StreamDecode的源码:

这个类的核心就是read()这个方法,由于这里直接操作InputStream进行read(),因此可以读取出2个字节,java中每两个字节转成一个字符。

这就是Reader可以读取字符的原因,只不过是利用InputStream先将字节读取出来,再按照一定的编码方式转码,因此这就是我前面所说的Reader也不能读取字符的原因,因为它只是读字节,转字符而言。

最后再说一说这个BufferedReader,和BufferedInputStream类似,它也是一个装饰者模式的类,接收一个Reader类,提供缓存功能。看看它的源码:

我们这里只研究它最简单的构造方法,它的构造函数接收一个Reader对象,并建立一个缓存,如果未指定缓存长度,就使用默认的长度。

BufferedReader的灵魂方法read()和BufferedInputStream的read()方法类似,都是采用了一个fill方法,可以参考 java io -- FilterInputStream 与 装饰者模式这篇文章。

如果没有数据就用fill去读取一块数据,放在缓存里,如果缓存里有数据,直接从缓存里读就OK了。

总结:这篇文章总结了Reader类的用法与原理,但是本文没有具体涉及java的编码问题,这是一个较大的话题,有兴趣的可以去网上参考其他文章。

java reader类子类_java io --- Reader类相关推荐

  1. java继承孙子类_Java:类与继承

    Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态 这四大特性都离不开类,只有存在类,才能体现面向对象编程的特点,今天我们就来了解一些类与继承的相关 ...

  2. java 枚举的继承_java中枚举类可以被继承吗?

    java 枚举类 java中,使用关键字enum来定义枚举类,枚举类是一个特殊的类,大部分功能和普通类是一样的,区别为: ● 枚举类继承了java.lang.Enum类,而不是默认的Object类.而 ...

  3. java web 初始化方法_Java Web(二) 类的初始化及初始化顺序

    1. 问题点 最近在写单例模式的时候碰到了@Autiwired注解注入为NULL的情况,研究一番,发现是和类的初始化顺序有关.先抛出我的问题: //异步处理 public class AsyncMan ...

  4. java 类爆炸_Java 封装与类

    一.面向对象编程 面向对象编程三大特性:封装.继承和多态. 类是实现封装的手段,是面向对象编程的基本单元. 封装隐藏了类的内部实现细节,暴露给外界可控的操作,提高数据的完整性和安全性,提高模块的可重用 ...

  5. java 日期格式常量_Java 日期格式类

    Java格式 - Java日期格式类 Java 8有新的Date-Time API来处理日期和时间. 我们应该使用新的Java 8 Date-Time API来格式化和解析日期时间值. 如果我们正在编 ...

  6. java接口作为参数_JAVA:将类、抽象类、接口当成方法的参数传入

    将类当成参数传入方法,其实就是将类的对象传入方法,如果是抽象类,其实就是将抽象类的子类的对象传入方法,如果是接口,其实就是将接口实现类的对象传入方法. 因为抽象类和接口是不能实例化成对象的,所以必须找 ...

  7. Java学习之子类(八):abstract类和abstract方法

    在设计程序的时候,我们会经常使用abstract类,原因是,abstract类只关心操作,而不关心这些操作具体的实现细节 细节应当由抽象类的非抽象子类去实现,这些子类可以给出具体的实例,来完成程序功能 ...

  8. java random函数用法_JAVA的Random类的用法详解

    Random类主要用来生成随机数,本文详解介绍了Random类的用法,希望能帮到大家. Random类 (java.util) Random类中实现的随机算法是伪随机,也就是有规则的随机.在进行随机时 ...

  9. 基于java洗浴中心管理系统_Java IO流详解

    流的概念和作用 学习Java IO,不得不提到的就是JavaIO流. 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...

  10. java字符流解析_Java IO(四):字符流详解

    一.字符流 字节流提供了处理任何类型输入/输出操作的功能(因为对于计算机而言,一切都是0和1,只需把数据以字节形式表示就够了),但它们不可以直接操作Unicode字符,因为一个Unicode字符占用2 ...

最新文章

  1. android用户界面之菜单(Menu)教程实例汇总
  2. 【MyBatis】myBatis动态传入表名进行查询
  3. QT,C++多项式计算器—version3(厌倦CMD黑框框的走起!)
  4. ios微信小程序下拉刷新怎么配_为什么他的下拉刷新是个动画效果?
  5. [IE9] 开发IE9上的屏幕取词功能
  6. Win2003中apache2整合tomcat5和iis6
  7. angular的html引入js,在AngularJS中的文件夹中加载JavaScript和CSS文件
  8. python 的案例实战_python案例实战之一
  9. 信号扫描_微观世界扫描电子显微镜(SEM)
  10. 计算机组成原理综合题,2013计算机组成原理复习题.doc
  11. 一个OSPF的区域备份在手册里看到的
  12. 第二百三十二节,Bootstrap排版样式
  13. 私藏的google浏览器插件
  14. 零基础如何学习java?
  15. python win32转pdf 横版_.doc使用python转换为pdf
  16. 全面分析游戏限制多开原理
  17. web端实现类微信的语音播放效果
  18. Java动态性——反射机制学习笔记
  19. 【阅读笔记】Towards Personalized Federated Learning个性化联邦综述
  20. 如何给单片机烧录程序?

热门文章

  1. wifi抓包/苹果电脑mac book抓wifi sniffer packet
  2. 计算经纬度距离工具类
  3. Java代码发送post请求工具类
  4. 【论文阅读】2018-基于深度学习的网络流量分类及异常检测方法研究_王伟
  5. ZZULIOJ1026
  6. 科研计算机视觉常用绘图软件,科研图形处理——除了R、Graphpad外,这款软件也不要错过哦!...
  7. 不小心删了sxos文件夹_如何恢复Mac废纸篓删除的文件
  8. matlab程序及C语言实现一维多元离散信源熵
  9. 信息论Matlab仿真——信源熵
  10. office2007每次打开都配置进度_每次打开excel2007都要配置进度怎么办?