详细整理JavaNio原理(二)

关注并转发 , 每天发送更多java技术文章 。
咱们接着上回的知识点来讲:
通道的基本原理:
既可以从通道中读取数据 , 又可以写数据到通道 。 但流的读写通常是单向的 。 通道可以异步地读写 。 通道中的数据总是要先读到一个Buffer , 或者总是要从一个Buffer中写入 。正如上面所说 , 从通道读取数据到缓冲区 , 从缓冲区写入数据到通道 。 如下图所示:
这些是JavaNIO中最重要的通道的实现:
FileChannel:从文件中读写数据 。 DatagramChannel:能通过UDP读写网络中的数据 。 SocketChannel:能通过TCP读写网络中的数据 。 ServerSocketChannel:可以监听新进来的TCP连接 , 像Web服务器那样 。 对每一个新进来的连接都会创建一个SocketChannel 。基本的Channel示例
下面是一个使用FileChannel读取数据到Buffer中的示例:
Java代码
RandomAccessFileaFile=newRandomAccessFile("data/nio-data.txt","rw");FileChannelinChannel=aFile.getChannel();ByteBufferbuf=ByteBuffer.allocate(48);intbytesRead=inChannel.read(buf);while(bytesRead!=-1){System.out.println("Read"+bytesRead);buf.flip();while(buf.hasRemaining()){System.out.print((char)buf.get());}buf.clear();bytesRead=inChannel.read(buf);}aFile.close();注意buf.flip()的调用 , 首先读取数据到Buffer , 然后反转Buffer,接着再从Buffer中读取数据 。 下一节会深入讲解Buffer的更多细节 。
缓冲区(Buffer)
JavaNIO中的Buffer用于和NIO通道进行交互 。 如你所知 , 数据是从通道读入缓冲区 , 从缓冲区写入到通道中的 。
缓冲区本质上是一块可以写入数据 , 然后可以从中读取数据的内存 。 这块内存被包装成NIOBuffer对象 , 并提供了一组方法 , 用来方便的访问该块内存 。
Buffer的基本用法
使用Buffer读写数据一般遵循以下四个步骤:
写入数据到Buffer调用flip()方法从Buffer中读取数据调用clear()方法或者compact()方法当向buffer写入数据时 , buffer会记录下写了多少数据 。 一旦要读取数据 , 需要通过flip()方法将Buffer从写模式切换到读模式 。 在读模式下 , 可以读取之前写入到buffer的所有数据 。
一旦读完了所有的数据 , 就需要清空缓冲区 , 让它可以再次被写入 。 有两种方式能清空缓冲区:调用clear()或compact()方法 。 clear()方法会清空整个缓冲区 。 compact()方法只会清除已经读过的数据 。 任何未读的数据都被移到缓冲区的起始处 , 新写入的数据将放到缓冲区未读数据的后面 。
下面是一个使用Buffer的例子:
Java代码
RandomAccessFileaFile=newRandomAccessFile("data/nio-data.txt","rw");FileChannelinChannel=aFile.getChannel();//createbufferwithcapacityof48bytesByteBufferbuf=ByteBuffer.allocate(48);intbytesRead=inChannel.read(buf);//readintobuffer.while(bytesRead!=-1){buf.flip();//makebufferreadyforreadwhile(buf.hasRemaining()){System.out.print((char)buf.get());//read1byteatatime}buf.clear();//makebufferreadyforwritingbytesRead=inChannel.read(buf);}aFile.close();Buffer的capacity,position和limit
缓冲区本质上是一块可以写入数据 , 然后可以从中读取数据的内存 。 这块内存被包装成NIOBuffer对象 , 并提供了一组方法 , 用来方便的访问该块内存 。
为了理解Buffer的工作原理 , 需要熟悉它的三个属性:
capacitypositionlimitposition和limit的含义取决于Buffer处在读模式还是写模式 。 不管Buffer处在什么模式 , capacity的含义总是一样的 。
这里有一个关于capacity , position和limit在读写模式中的说明 , 详细的解释在插图后面 。
作为一个内存块 , Buffer有一个固定的大小值 , 也叫“capacity”.你只能往里写capacity个byte、long , char等类型 。 一旦Buffer满了 , 需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据 。
position
当你写数据到Buffer中时 , position表示当前的位置 。 初始的position值为0.当一个byte、long等数据写到Buffer后 , position会向前移动到下一个可插入数据的Buffer单元 。 position最大可为capacity–1 。
当读取数据时 , 也是从某个特定位置读 。 当将Buffer从写模式切换到读模式 , position会被重置为0 。 当从Buffer的position处读取数据时 , position向前移动到下一个可读的位置 。
【详细整理JavaNio原理(二)】limit
在写模式下 , Buffer的limit表示你最多能往Buffer里写多少数据 。 写模式下 , limit等于Buffer的capacity 。
当切换Buffer到读模式时 , limit表示你最多能读到多少数据 。 因此 , 当切换Buffer到读模式时 , limit会被设置成写模式下的position值 。 换句话说 , 你能读到之前写入的所有数据(limit被设置成已写数据的数量 , 这个值在写模式下就是position)
Buffer的类型
JavaNIO有以下Buffer类型:
ByteBufferMappedByteBufferCharBufferDoubleBufferFloatBufferIntBufferLongBufferShortBuffer如你所见 , 这些Buffer类型代表了不同的数据类型 。 换句话说 , 就是可以通过char , short , int , long , float或double类型来操作缓冲区中的字节 。
MappedByteBuffer有些特别 , 在涉及它的专门章节中再讲 。
原文链接:


    推荐阅读