Saul's blog Saul's blog
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)

Saul.J.Wu

立身之本,不在高低。
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)
  • Java入门基础

  • Java核心基础

    • 多线程

    • Java常用类

    • 枚举类与注解

    • Java集合

    • 数据结构与算法

    • 泛型

    • IO流

      • IO流概述
        • 概念
        • Java IO原理
        • 流的分类
        • InputStream / OutputStream
        • Reader / Writer
        • 同步和异步
        • 小结
      • File对象
      • InputStream
      • OutputStream
      • Filter模式
      • 操作Zip
      • 读取classpath资源
      • 序列化
      • Reader
      • Writer
      • 转换流
      • PrintStream和PrintWriter
      • RandomAccessFile
      • Files工具类
    • 网络编程

    • 反射

    • 函数式编程

  • 设计模式

  • Web开发

  • SpringBoot

  • 微服务

  • Elasticsearch

  • 运维

  • 后端
  • Java核心基础
  • IO流
SaulJWu
2021-01-07

IO流概述

# 概念

IO是指Input/Output,即输入和输出。以内存为中心:

  • Input指从外部读入数据到内存,例如,把文件从磁盘读取到内存,从网络读取数据到内存等等。
  • Output指把数据从内存输出到外部,例如,把数据从内存写入到文件,把数据从内存输出到网络等等。

为什么要把数据读到内存才能处理这些数据?因为代码是在内存中运行的,数据也必须读到内存,最终的表示方式无非是byte数组,字符串等,都必须存放在内存里。

从Java代码来看,输入实际上就是从外部,例如,硬盘上的某个文件,把内容读到内存,并且以Java提供的某种数据类型表示,例如,byte[],String,这样,后续代码才能处理这些数据。

因为内存有“易失性”的特点,所以必须把处理后的数据以某种方式输出,例如,写入到文件。Output实际上就是把Java表示的数据格式,例如,byte[],String等输出到某个地方。

IO流是一种顺序读写数据的模式,它的特点是单向流动。数据类似自来水一样在水管中流动,所以我们把它称为IO流。

java-io

# Java IO原理

  • I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。
  • Java程序中,对于数据的输入/输出操作以“流(stream)”的方式进行。
  • java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。

image-20210107183132236

# 流的分类

  • 按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)。
  • 按数据流的流向不同分为:输入流,输出流
  • 按流的角色的不同分为:节点流,处理流
抽象基类 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
  • 1、Java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的
  • 2、由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

image-20210107183705165

  • IO流体系

image-20210107184041032

节点流和处理流:

  • 节点流:直接从数据源或目的地读写数据。

image-20210107184329592

  • 处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。

image-20210107184343414

# InputStream / OutputStream

IO流以byte(字节)为最小单位,因此也称为字节流。

例如,我们要从磁盘读入一个文件,包含6个字节,就相当于读入了6个字节的数据:

╔════════════╗
║   Memory   ║
╚════════════╝
       ▲
       │0x48
       │0x65
       │0x6c
       │0x6c
       │0x6f
       │0x21
 ╔═══════════╗
 ║ Hard Disk ║
 ╚═══════════╝
1
2
3
4
5
6
7
8
9
10
11
12
13

这6个字节是按顺序读入的,所以是输入字节流。

反过来,我们把6个字节从内存写入磁盘文件,就是输出字节流:

╔════════════╗
║   Memory   ║
╚════════════╝
       │0x21
       │0x6f
       │0x6c
       │0x6c
       │0x65
       │0x48
       ▼
 ╔═══════════╗
 ║ Hard Disk ║
 ╚═══════════╝
1
2
3
4
5
6
7
8
9
10
11
12
13

在Java中,InputStream代表输入字节流,OuputStream代表输出字节流,这是最基本的两种IO流。

# Reader / Writer

如果我们需要读写的是字符,并且字符不全是单字节表示的ASCII字符,那么,按照char来读写显然更方便,这种流称为字符流。

Java提供了Reader和Writer表示字符流,字符流传输的最小数据单位是char。

例如,我们把char[]数组Hi你好这4个字符用Writer字符流写入文件,并且使用UTF-8编码,得到的最终文件内容是8个字节,英文字符H和i各占一个字节,中文字符你好各占3个字节:

0x48
0x69
0xe4bda0
0xe5a5bd
1
2
3
4

反过来,我们用Reader读取以UTF-8编码的这8个字节,会从Reader中得到Hi你好这4个字符。

因此,Reader和Writer本质上是一个能自动编解码的InputStream和OutputStream。

使用Reader,数据源虽然是字节,但我们读入的数据都是char类型的字符,原因是Reader内部把读入的byte做了解码,转换成了char。使用InputStream,我们读入的数据和原始二进制数据一模一样,是byte[]数组,但是我们可以自己把二进制byte[]数组按照某种编码转换为字符串。究竟使用Reader还是InputStream,要取决于具体的使用场景。如果数据源不是文本,就只能使用InputStream,如果数据源是文本,使用Reader更方便一些。Writer和OutputStream是类似的。

# 同步和异步

同步IO是指,读写IO时代码必须等待数据返回后才继续执行后续代码,它的优点是代码编写简单,缺点是CPU执行效率低。

而异步IO是指,读写IO时仅发出请求,然后立刻执行后续代码,它的优点是CPU执行效率高,缺点是代码编写复杂。

Java标准库的包java.io提供了同步IO,而java.nio则是异步IO。上面我们讨论的InputStream、OutputStream、Reader和Writer都是同步IO的抽象类,对应的具体实现类,以文件为例,有FileInputStream、FileOutputStream、FileReader和FileWriter。

本节我们只讨论Java的同步IO,即输入/输出流的IO模型。

# 小结

IO流是一种流式的数据输入/输出模型:

  • 二进制数据以byte为最小单位在InputStream/OutputStream中单向流动;
  • 字符数据以char为最小单位在Reader/Writer中单向流动。

Java标准库的java.io包提供了同步IO功能:

  • 字节流接口:InputStream/OutputStream;适合处理图像音频等非文本文件。
  • 字符流接口:Reader/Writer。适合处理文本文件。
帮我改善此页面 (opens new window)
#IO#流#字节#字符
上次更新: 2021/02/08, 11:20:26
通配符
File对象

← 通配符 File对象→

最近更新
01
zabbix学习笔记二
02-28
02
zabbix学习笔记一
02-10
03
Linux访问不了github
12-08
更多文章>
Theme by Vdoing | Copyright © 2020-2022 Saul.J.Wu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式