前言
让时光积累真正的价值
最近在学习netty,要了解NIO,还是要对IO有一定的了解才行。之前看到了《Java IO,硬骨头也能变软》感觉写的非常的不错,但是我没有好好的做笔记,到后来都忘记了很多内容。
借这这个机会好好的做一个笔记。
这一篇笔记,主要是对JavaIO进行一个分类,方便自己好好记忆。
按照操作方式对IO进行分类
按照这种分类的方式,又可以再将IO流分成3类:
- 字符流和字节流
- 读流和写流\输入流和输出流
- 节点流和处理流
字符流和字节流的特点
字符流:
- 以字符为单位,每次读写都是操作8位数据,只能操作字符数据
字节流:
- 以字节为单位,每次读写都是操作16位数据,能操作任意数据
在Java的原始版本中(java1.0),只有字节流,没有字符流。在Java1.1版本才把字符流加到IO的体系中。
需要特别注意:
所有的IO在最底层都是通过字节来交互的,字符流是一个经过了包装的字节流。提供字符流的目的是方便开发者操作字符数据。
怎么分辨字符流和字节流?
可以从类名来分辨,如果类名是xxxxReader或xxxxWriter的类基本上就是字符流了。
而类名是xxxOutputStream、xxxxInputStream结尾的基本上是字节流。
怎样把字节流转化为字符流?
很多时候,我们使用IO是在做一些字符串的操作。但是系统给我们提供的基础流都是一些字节流。我们常常需要将原来字节流转化为字符流。
有两个例子:
- 获取键盘输入
BufferReader buffer = new BufferReader(new InputStreamReader(System.in));
复制代码
使用IO库提供的InputStreamReader,可以将InputStream转化为Reader流。配合缓冲流的包装就可以愉快的获取键盘的输入了。
- 写入字符串到文件
File sdf = new File("/");
FileOutputStream stream = new FileOutputStream(sdf);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
writer.write("hell world");
复制代码
使用IO库提供的OutputStreamWriter,可以将OutputStream转化为Writer流。配合缓冲流的包装就可以直接向文件写入字符串了。
当然,这里也可以直接获取文件的字符流(FileWriter)来操作
输入流和输出流的特点
首先,输入和输出这两个概念都是相对与内存(或者是应用程序)来说的。
理解了这一个概念,什么是输入流什么是输出流很很容易分辨清楚了。
从外部载入到内存,比如xxxxReader、xxxxInputStream就是属于输入流。
从内存写到外部,比如xxxxWriter、xxxxOutputStream就是属于输出流。
节点流和处理流的特点
节点流:
- 直接以外设为数据源或者的数据目的地,直接进行读取或者输出的操作,AIP相对不友好
操作流(过滤流):
- 对已经存在节点流做一个包装,在节点流上封装一层用户友好的API
按照操作对象对IO进行分类
JavaIO 库中提供了一种链接的机制,可以将一个流套接到另外一个流上 ,最终形成一个流的管道链接,这种方式是装饰模式(设计模式)的典型应用。其中节点流就是装饰的原型(Component)。
操作流(过滤流):
- 缓冲操作
- 基本数据类型操作
- 对象序列化操作
- 转化控制
- 打印控制
节点流:
- 文件操作
- 管道操作
- 数组操作
缓冲操作:
在操作流的时候先将数据写入一个缓冲区,可以避免直接和硬盘、外设等速度非常缓慢的IO设备打交道,节约了大量的等待时间。
比如键盘输入的例子,将字节流转换为字符流之后,BufferedReader先将数据添加到缓冲区,等到一定的条件之后才将数据从缓冲区里面取出来。
缓冲操作流有:
- BufferedReader
- BufferedWriter
- BufferedInputStream
- BufferedOutputStream
基本数据类型操作:
内存与外设之间传输数据一般都是以0101的数据来做交互,如果要传输一个基本数据类型(int、sort、long)怎么办?
我们可以使用基本数据类型转换流来套接字节流,这样就可以向流的另外一段传送一个Java的基本数据类型了。
基本类型转换流有:
- DataOutputStream
- DataInputStream
对象序列化操作:
怎么将一个Java的对象,转化成0101数据传送到流的另外一端?Java提供了对象序列化转化流解决这个问题。
对象序列化相关的流有:
- ObjectOutputStream
- ObjectIntputStream
转化控制:
想要直接操作字符串,但是原生流是字节流,怎么办?
可以使用转化流将字节流转化为字符流
转化流有:
- InputStreamReader
- OutputStreamReader
打印控制:
提供了很多打印相关的便利操作,其中system.out就是一个打印流。不限于命令行打印,我们可以使用println、printfAPI对任意的外设进行操作。
打印流有:
- PrintStream
- PrintWriter
文件操作:
对应外设是文件,我们可以提供Java提供的API打开相关的文件字符流、文件字节流。文件流提供输入流、输出流、字节流、字符流。
文件流有:
- FileWriter
- FileReader
- FileOutputStream
- FileInputStream
管道操作
查阅资料,管道流是用来在线程之间传输数据的,没怎么了解过。
管道流有:
- PipedInputStream
- PipedOutStream
- PipedReader
- PipedWriter
数组流:
在内存中开辟一块数组作为数据源。有一个特点就是可重复读取。在有重复读取需求的地方将数据源的数据加载进数组流中,然后就可以重复从数组流中读取数据了。但是这样做有可能会对内存造成太大的负担。
数组流有:
- ByteArrayInputStream
- ByteArrayOutputStream
- charArrayReader
- charArrayWriter
最后
参考:《Java IO,硬骨头也能变软》