一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
在我们日常开发中,有很多情况,需要从某个位置读取或者上传数据。这些数据可能是文件、图片,或者是文本、压缩包等等。java 中对数据输入输出的方式有很多种,今天大概介绍Java 输入输出的基本概念。
输入输出流的概念的理解
在Java 中,涉及到输入输出功能的相关类几乎都在java.io 包中。就包含了上面的五个类。
所有这些java.io 包中的类都可以称作“流类”。这些流类其实本质代表的就是输入数据源或者输出目标。
所以说,一个“流”,就可以理解为一个数据的序列。
对于输入和输出的理解有时候会使我们迷惑。我们可以这么记:你的主机(或者程序、电脑)是主角,输入的“入”字的目标就是你的主机;而输出的“出”的意思就是从你的主机中输出。
所以说,输入流就代表从一个源读取的数据;而输出流就代表向一个目标写的数据。
java.io 包中的“流类”支持很多种数据格式,不仅可以应用到本地文件的传输,同时可以在网络编程中发挥作用。
Java 中输入输出流的几个基本类
在Java 中和IO 相关的主要有这几个类:File / InputStream / OutputStream / Reader / Writer。
其中后四个都是抽象类。
InputStream / OutputStream 是字节输入输出流;Reader / Writer 是字符输入输出流。
从几个类的命名我们就可以看出,File 类的主要功能是处理文件(文件夹)的,其他四个类是处理数据的。
几个抽象类常用的实现类的概念及区别
InputStream / OutputStream / Reader / Writer 四个都是抽象类,前两个是字符流的顶级类;后两个是字节流的顶级类。
对于这几个类分别有多个对应的实现子类,现在挑几个常用的做一个基本的概念性的讲解,便于之后文章的理解。
FileInputStream(FileOutputStream)与FileReader(FileWriter)
FileInputStream(FileOutputStream) 是字节流;FileReader(FileWriter) 是字符流。
二者的区别就是这个“流”以字节为单位还是以字符为单位。
我们都知道,汉字的编码和英文字母不同。一个汉字是一个字符,但是会占用两个字节。
在用字节流读取中文的时候,可能会出现乱码;而用字符流则不会出现乱码。
这是因为字节流是以一个字节为读取单位的,而字符流是以一个字符为读取单位的。同时用字符流读取的速度比字节流要快。这是最常用的并可以作为区别的地方,其他基本用法差不多。
ObjectOutputStream 与ByteArrayOutputStream
ObjectOutputStream, 根据其名字就可以知道,是操作Object(对象)的。ObjectOutputStream 可以将java对象写入outputstream流中(其实就是序列化),然后进行持久化。被操作的这个对象必须是实现了java.io.Serializable 接口(只有实现了这个接口的对象才可以进行序列化)。
而ByteArrayOutputStream 的作用则是将数据写入byte 数组中。
InputStreamReader和OutputStreamWriter
这两个的命名其实叫做转换流。其作用是为了将字节流InputStream 和OutputStream 转换为字符流,这样可以提高文件的传输速度。
使用方法为:
- public InputStreamReader(InputStream in)
- public InputSreamReader(InputStream in,String charsetName)
总结
Java的IO模型设计得十分优秀。
IO 模型使用了装饰者(Decorator)模式,按功能划分Stream。
我们可以动态装配这些Stream,以便获得您需要的功能。
如:当我们需要一个具有缓冲的文件输入流的使用,我们可以选择组合使用FileInputStream和BufferedInputStream 以完成我们目标程序的开发。
展望
之后的文章我们会深入每个具体的类做具体的讲解。同时也会涉及一些“高级玩法”。
附一张各个输入输出流的类之间的关系图,以作参考。