最近看疯狂java讲义整理一下nio。传统io的读写方法都是阻塞式的,自JDK1.4之后,java提供了一系列改进的输入/输出功能,称之为new io(nio)。Channel(通道)和Buffer(缓冲)是nio的2个新对象,channel与InputSteam,outputSteam最大的区别就是提供了一个map方法,通过该map方法可以直接将一块数据映射到内存区域中,如果说传统io是面向流的处理,那么nio是面向“块”的处理。
1.传统io的流对象如图
2.nio的buffer对象
buffer对象有三个概念,容量(capacity),界限(limit),位置(position)
容量(capacity):缓冲区的的容量(capacity)表示该Buffer的最大数据容量。
界限(limit):第一个不应该被读出或者写入的缓冲区位置索引。也就是位于limit后的数据即不可被读,也不可被写
位置(position):用于指明下一个可以被读出的或者写入的缓冲区位置索引
如图:
buffer主要作用是装入数据,然后输出数据。类似传统io中自己创建一个byte[],当buffer装入数据结束后,调用buffer的flip(),该方法将limit设置为position所在位置,并将position设置为0。也就是说flip方法是输出数据做好准备。当buffer输出数据结束后,调用clear()方法,clear不是清空buffer的数据,而是将position设置为0,limit设置为和capacity一样。
下面是测试代码
执行结果如下:
2.channel对象
channel与传统的流对象很类似,主要由2个区别
1.channel可以将指定文件的部分或者全部映射成Buffer 2.程序不能直接访问channel中的数据,channel必须与buffer进行交互,pipe.SourceChannel 支持线程之间通信的管道channel ServerSocketChannel SocketChannel是tcp协议通信channel, DatagramChannel 是 UDP channel。可以说 nio必须是channel对象和buffer一起使用
如上图代码,只是将一个java代码复制到一个a.txt中。如果使用gbk编码会报错java.nio.charset.MalformedInputException: Input length = 1,因为该源码里面有中文,网上查了一下是因为 中文gbk是2个字节,utf-8是3个字节,意思是多了半个汉字导致这种问题。
传统io去读一个文件的时候,通过while循环去读放入一个字节数组中。nio也可以通过这种方式去读,虽然map()方法把一个文件数据全部映射到buffer中,但是有时候文件有可能会非常大。
如下面代码: