java io 缓冲流_吃透Java IO:字节流、字符流、缓冲流

前言

IO流是Java中的一个重要构成部分,也是我们经常打交道的。这篇关于Java IO的博文干货满满,堪称全网前三(请轻喷!)

下面几个问题(问题还会继续补充),如果你能对答如流,那么恭喜你,IO知识掌握得很好,可以立即关闭文章。反之,你可以在后面得文章中寻找答案。

1. Java IO流有什么特点?

2. Java IO流分为几种类型?

3. 字节流和字符流的关系与区别?

4. 字符流是否使用了缓冲?

5. 缓冲流的效率一定高吗?为什么?

6. 缓冲流体现了Java中的哪种设计模式思想?

7. 为什么要实现序列化?如何实现序列化?

8. 序列化数据后,再次修改类文件,读取数据会出问题,如何解决呢?

1 初识Java IO

IO,即 in 和 out,也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。

Java 中是通过流处理IO 的,那么什么是流?

流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。

当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

一般来说关于流的特性有下面几点:

1. 先进先出:最先写入输出流的数据最先被输入流读取到。

2. 顺序存取:可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(`RandomAccessFile`除外)

3. 只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

1.1 IO流分类

IO流主要的分类方式有以下3种:

1. 按数据流的方向:输入流、输出流

2. 按处理数据单位:字节流、字符流

3. 按功能:节点流、处理流

c845841013e59009efe6def3dfc6a8bd.png

1、输入流与输出流

输入与输出是相对于应用程序而言的,比如文件读写,读取文件是输入流,写文件是输出流,这点很容易搞反。

dd9ad64ad96641bdd1d8f9b75a5766c8.png

2、字节流与字符流

字节流和字符流的用法几乎完成全一样,区别在于字节流和字符流所操作的数据单元不同,字节流操作的单元是数据单元是8位的字节,字符流操作的是数据单元为16位的字符。

为什么要有字符流?

Java中字符是采用Unicode标准,Unicode 编码中,一个英文为一个字节,一个中文为两个字节。

1ad44bf3020036b43c83e4f9f6aa1313.png

而在UTF-8编码中,一个中文字符是3个字节。例如下面图中,“云深不知处”5个中文对应的是15个字节:-28-70-111-26-73-79-28-72-115-25-97-91-27-92-124

6266e44a20dbaae0f8a0b0292fc2f8f1.png

那么问题来了,如果使用字节流处理中文,如果一次读写一个字符对应的字节数就不会有问题,一旦将一个字符对应的字节分裂开来,就会出现乱码了。为了更方便地处理中文这些字符,Java就推出了字符流。

字节流和字符流的其他区别:

1. 字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。

2. 字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。详见文末效率对比。

以写文件为例,我们查看字符流的源码,发现确实有利用到缓冲区:

7ccb654712cf5b9ed6bd126fe021cb94.png

264cb2abf22e5c09298dcc9b4e50aafe.png

3、节点流和处理流

节点流:直接操作数据读写的流类,比如`FileInputStream`

处理流:对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能,例如`BufferedInputStream`(缓冲字节流)

处理流和节点流应用了Java的装饰者设计模式。

下图就很形象地描绘了节点流和处理流,处理流是对节点流的封装,最终的数据处理还是由节点流完成的。

612894c6b4a7ed00ad3d6a6405ceb88e.png

在诸多处理流中,有一个非常重要,那就是缓冲流。

我们知道,程序与磁盘的交互相对于内存运算是很慢的,容易成为程序的性能瓶颈。减少程序与磁盘的交互,是提升程序效率一种有效手段。缓冲流,就应用这种思路:普通流每次读写一个字节,而缓冲流在内存中设置一个缓存区,缓冲区先存储足够的待操作数据后,再与内存或磁盘进行交互。这样,在总数据量不变的情况下,通过提高每次交互的数据量,减少了交互次数。

214ca95a4aacd8fd3ec9d07c1d9350fa.png

联想一下生活中的例子,我们搬砖的时候,一块一块地往车上装肯定是很低效的。我们可以使用一个小推车,先把砖装到小推车上,再把这小推车推到车前,把砖装到车上。这个例子中,小推车可以视为缓冲区,小推车的存在,减少了我们装车次数,从而提高了效率。

32202576d261d30e3d15b608cd8de9c8.png

需要注意的是,缓冲流效率一定高吗?不一定,某些情形下,缓冲流效率反而更低,具体请见IO流效率对比。

完整的IO分类图如下:

b909fe2ba60c0bbf30b2b6a82d94bc51.png

1.2 案例实操

接下来,我们看看如何使用Java IO。

文本读写的例子:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值