Java 输入输出相关概念介绍(File、IO 流)(三)

227 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

上一篇文章:Java 输入输出相关概念介绍(File、IO 流)(二) 介绍了File 类的含义及使用,本篇文章我们将围绕IO 流的相关基本概念及使用方法进行讲解。

流的基本概念分类

  1. Java 中,根据待处理的数据的类型的不同分为:字符流和字节流。
  2. 同时根据数据流的流向向不同,可以分为:输入流和输出流。

常用实现类的介绍

在此系列第一篇文章中有做过介绍,对于字节流、字符流,与输入流、输出流可以两两组合,形成四个不同的抽象类: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 提供的功能,遇到不同类型的数据流,然而我们的目标数据类型却不一样,这个时候就需要用到“转换流”。

同时我们需要对着几个概念再做进一步的理解

  1. 字节流:将字节读取到内存或者将字节写入到实体硬盘文件里面。

  2. 字符流:将硬盘或者其他某些位置的字节转换为字符(读入到系统中);或者将字符转换为字节(输出到目标位置)。所以我们也可以认为,字符只存在于系统程序中。

  3. 转换流:将字节数据按照指定的编码格式转换为字符(读入到程序中),或者将程序中的字符数据按照我们需要的指定的编码格式,转换为字节(写出到目标)。所以这个转换流是字节(字符)通向字符(字节)的一个桥梁。

转换流的特点

  • 转换流顾名思义,就是是字符流和字节流之间进行转换的纽带
  • 因为不同类型的字符有不同的编码方式,所以对于读取到的字节数,需要据经过指定编码,然后就可以转换成字符
  • 同理,转换流可对读取到的字符数据经过指定编码转换成字节数据

使用转换流的场景

  • 字节数据和字符数据二者之间需要转换时,如调用的api 返回的结果不是预期的时候
  • 对于某个流操作的数据,需要对这些数据进行编码或者需要解码的时候

具体可以使用的实现子类

根据上述第一条到第三条的概念描述,我们可以知道,字节到字符的转换只在输入流中生效;字符到字节在输出流中生效。

  • 字节到字符的转换使用:InputStreamReader
  • 字符到字节的桥梁使用:OutputStreamWriter

总结展望

本篇文章主要介绍了Java 流的概念及用法分析,还有使用场景。

后续文章会具体介绍具体的实现子类的使用。