一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
上一篇文章:Java 输入输出相关概念介绍(File、IO 流)(二) 介绍了File 类的含义及使用,本篇文章我们将围绕IO 流的相关基本概念及使用方法进行讲解。
流的基本概念分类
- Java 中,根据待处理的数据的类型的不同分为:字符流和字节流。
- 同时根据数据流的流向向不同,可以分为:输入流和输出流。
常用实现类的介绍
在此系列第一篇文章中有做过介绍,对于字节流、字符流,与输入流、输出流可以两两组合,形成四个不同的抽象类:InputStream/OutputStream/Reader/Writer。
这四个分别是字节输入流、字节输出流、字符输入流、字符输出流。
对于这几个抽象类都有很多对应的子类实现,根据不同的应用场景,应该挑选合适类去使用。
用法分析
我们都是知道,流的顶级抽象类下有很多子类实现,决定使用哪个类,判断使用对应的哪个构造进程的通用准则包含以下几条:
- 数据流向是输入还是输出。
- 数据来自哪里(数据源是什么),数据流向哪里,比如:文件、内存、网络。
- 最原始的数据格式是什么,比如是否是文本数据。
- 数据传输的过程中是否要缓冲。
- 是否要格式化输出。
- 是否需要转换流(转换流的概念在之后会讲解,或者读者可以自行查阅)。转换流一般使用这两个实现:InputStreamReader, OutputStreamWriter。
实现类用法 - 具体描述
按输入输出流向
输入:Reader, InputStream 的子类实现;
输出:Writer, OutputStream 的子类实现
按数据来源(数据流向)
- 如果对应的数据是文件,那么选择:FileInputStream, FileOutputStream, FileReader, FileWriter
- 如果来自byte[](其实这就是字节形式):ByteArrayInputStream, ByteArrayOutputStream
- 如果来自Char[](字符形式): CharArrayReader, CharArrayWriter
- 如果是String,那么使用:StringBufferInputStream, StringReader, StringWriter
- 如果网络数据流:InputStream, OutputStream, Reader, Writer
按数据格式使用
- 二进制格式(只要不能确定是纯文本的都可以使用这个,其实就是“按字节”): InputStream, OutputStream及所有以Stream 结束的子类。
- 纯文本格式(含纯英文与汉字或其他编码方式);Reader, Writer及其所有带Reader, Writer的子类
是否格式化输出
如果需要格式化输出,那么使用:PrintStream, PrintWriter
是否需要缓冲
英文buffer 就是“缓冲” 的意思,所以如果需要缓冲,那么使用:BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter。
是否需要转换流
从Stream到Reader,Writer的转换,需要使用:InputStreamReader, OutputStreamWriter
一些非常用情况
除了上述几种情况以外,Java IO 还针对一些特殊场景提供了具体的实现子类
- 对象输入输出 使用:ObjectInputStream, ObjectOutputStream
- 进程间通信 PipeInputStream, PipeOutputStream, PipeReader, PipeWriter
字符流与字节流转换
我们在读取数据的时候,可能使用某些api 提供的功能,遇到不同类型的数据流,然而我们的目标数据类型却不一样,这个时候就需要用到“转换流”。
同时我们需要对着几个概念再做进一步的理解
-
字节流:将字节读取到内存或者将字节写入到实体硬盘文件里面。
-
字符流:将硬盘或者其他某些位置的字节转换为字符(读入到系统中);或者将字符转换为字节(输出到目标位置)。所以我们也可以认为,字符只存在于系统程序中。
-
转换流:将字节数据按照指定的编码格式转换为字符(读入到程序中),或者将程序中的字符数据按照我们需要的指定的编码格式,转换为字节(写出到目标)。所以这个转换流是字节(字符)通向字符(字节)的一个桥梁。
转换流的特点
- 转换流顾名思义,就是是字符流和字节流之间进行转换的纽带
- 因为不同类型的字符有不同的编码方式,所以对于读取到的字节数,需要据经过指定编码,然后就可以转换成字符
- 同理,转换流可对读取到的字符数据经过指定编码转换成字节数据
使用转换流的场景
- 字节数据和字符数据二者之间需要转换时,如调用的api 返回的结果不是预期的时候
- 对于某个流操作的数据,需要对这些数据进行编码或者需要解码的时候
具体可以使用的实现子类
根据上述第一条到第三条的概念描述,我们可以知道,字节到字符的转换只在输入流中生效;字符到字节在输出流中生效。
- 字节到字符的转换使用:InputStreamReader
- 字符到字节的桥梁使用:OutputStreamWriter
总结展望
本篇文章主要介绍了Java 流的概念及用法分析,还有使用场景。
后续文章会具体介绍具体的实现子类的使用。