【语言学习】JAVA IO和NIO - hippowc/hippowc.github.io GitHub Wiki
IO
java的IO流涉及到40多个类,看上去很混乱,但实际上是有规则的,而且彼此之间存在紧密的联系。它们都是从如下四个基类派生的:
- InputStream:字节输入流
- OutputStream:字节输出流
- Reader:字符输入流
- Writer:字符输出流
IO分类
按照流的流向分,可以分为输入流和输出流:
- 输入流
- 输出流
按照操作单元划分,可以划分为字节流和字符流:
- 字符读写
- 字节读写
按照流的角色划分为节点流和处理流,简单来说就是流是否直接与特定的地方(如磁盘、内存、设备等)相连;
- 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader
- 处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
可以将IO进行如下分类:
-- Reader -- 节点流 -- FileReader, PipedReader, CharArrayReader
-- 处理流 -- BufferedReader, InputStreamReader
-- Writer -- 节点流 -- FileWriter, PipedWriter, CharArrayWriter
-- 处理流 -- BufferedWriter, OutputStreamWriter, PrintWriter
-- InputStream -- 节点流 -- FileInputStream, PipedInputStream, ByteArrayInputStream
-- 处理流 -- BufferedInputStream, DataInputStream, ObjectInputStream, SequenceInputStream
-- OutputStream -- 节点流 -- FileOutputStream, PipedOutputStream, ByteArrayOutputStream
-- 处理流 -- BufferedOutputStream, DataOutputStream, ObjectOutputStream, PrintStream
按操作对象分类
-- 处理流 -- 缓冲操作:Buffered
-- 基本数据类型操作:Data
-- 对象序列化:Object
-- 转化控制:InputStreamReader, OutputStreamWriter
-- 打印控制:Print
-- 节点流 -- 文件操作:File
-- 管道操作:Piped
-- 数组操作或者说内存操作:ByteArray, CharArray
一些使用实战
- 节点流和处理流结合使用时,最好注意关闭顺序,譬如先关闭处理流,再关闭节点流;或者只关闭处理流,处理流会自动关闭对应的节点流。不过关闭处理流后,节点流就已经关闭了,再调用节点流的关闭,也不会报错
- 流写入完成后要注意flush或者finish,譬如GZIPOutputStream要使用finish,否则压缩包会有问题。
- 关于如何将一个InputStream的内容读到内存(byte数组中),使用input.read(buffer)方法,可以将内容读到buffer中,但是最好不要直接声明一个byte[]数组,采用这种方式读,因为不知道可以读多少内容(不知道数组设为多大),会造成内容不一致。最好还是使用ByteOutputStream来读取,先将inputstream的内容读到buffer中,可以知道读取了多少,然后使用bos.write(buffer, 0, n);可以精确的将buffer中的n长度写入bos中,直接通过toByteArray获取,当然要记得flush,只有output需要flush,input不需要
NIO
非阻塞的意义在于可以使用一个线程对大量的数据连接进行处理,非常适用于"短数据长连接"的应用场景,例如即时通讯软件。在一个阻塞C/S系统中,服务器要为每一个客户连接开启一个线程阻塞等待客户端发送的消息.若使用非阻塞技术,服务器可以使用一个线程对连接进行轮询,无须阻塞等待.这大大减少了内存资源的浪费,也避免了服务器在客户线程中不断切换带来的CPU消耗,服务器对CPU的有效使用率大大提高
NIO的核心概念包括Channel,Selector,SelectionKey,Buffer。
Channel是I/O通道,可以向其注册Selector,应用成功可以通过select操作获取当前通道已经准备好的可以无阻塞执行的操作.这由SelectionKey表示。
SelectionKey的常量字段SelectionKey.OP_***分别对应Channel的几种操作例如connect(),accept(),read(),write()。
select操作后得到SelectionKey.OP_WRITE或者READ即可在Channel上面无阻塞调用read和write方法,Channel的读写操作均需要通过Buffer进行.即读是讲数据从通道中读入Buffer然后做进一步处理.写需要先将数据写入Buffer然后通道接收Buffer。
NIO实现原理与IO的区别
不仅仅是代码包装的区别,是底层系统调用的区别。