Java NIO 包含几个核心的组件:
可以理解为资源的一个流,通过这个流资源可以从Channel读取Data到一个Buffer中或者从一个Buffer中写入Data到Channel;
集中Jdk7常用的Channel上线
Read Data from Channel
RandomAccessFile
aFile =newRandomAccessFile("data/nio-data.txt","rw");FileChannel
inChannel = aFile.getChannel();ByteBuffer
buf =ByteBuffer.allocate(48);//write
data to bufferint
bytesRead = inChannel.read(buf);while(bytesRead!=-1){System.out.println("Read
" + bytesRead);//swither
buffer type to read data from bufferbuf.flip();while(buf.hasRemaining()){System.out.print((char)
buf.get());}buf.clear();bytesRead=
inChannel.read(buf);}aFile.close();Java NIO Buffers 和Channels配合使用,Read from channels into buffer ,writtern from buffers into channels
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt" , "rw");FileChannel inChannel = aFile.getChannel();//Create Buffer with capacity of 48 byteByteBuffer buf = ByteBuffer.allocate(48);int bytesRead = inChannel.read(buf);while(bytesRead!=-1){buf.flip(); //make buffer ready for readwhile(buf.hasRemaining()){System.out.print((char) buf.get()); // read 1 byte at a time}buf.clear(); //make buffer ready for writingbytesRead = inChannel.read(buf);}
Buffer在创建的时候会分配规定大小的内存块,并且在buffer写入数据时只能写入这个固定大小的数据。如果Buffer已经放满数据,就需要先read 或者 clear 只能才能继续写入。
Position 在读模式和模式下面含义不一样。Bufer init之后Position值为0,当数据写入one byte ,long etc Buffer Position相应的移动到下一个位置。并且Position<=Capacity-1
当调用filp()从Buffer读取数据时会set position = 0,position会随着读取过程向下移动;
在Write模式下,Limit等于Capacity的值,表示能写多少数据到Buffer中。
调用filp()进入Reade模式会set limit = position ,表示最多能读的数据量。
通过使用allocate() 来分配Buffer大小
ByteBuffer buf = ByteBuffer.allocate(48);
CharBuffer buf = CharBuffer.allocate(1024);
向Buffer中写入数据有两种方法:
put() 方法写入数据 int bytesRead = inChannel.read(buf); //read into buffer.
buf.put(127);
转换写状态到读状态,发生动作:set limit = position ; set position=0 ;
两种方法:
get() etc //read from buffer into channel.
int bytesWritten = inChannel.write(buf);
byte aByte = buf.get();
set position=0
mark用于打点记录position为止,之后使用reset方法可以将position重置到mark记录的位置。
Channel 可以执行读取操作将数据读取到多个Buffer中。
Channel 可以执行写操作将多个Buffer的数据写入Channle中。
Channel 可以在Channle之间做转换包括transferFrom() & transferTo
例如我将html的header部分读取到第一个buffer中,将body部分读取到第二个Buffer中
ByteBuffer header = ByteBuffer.allocate(128);ByteBuffer body = ByteBuffer.allocate(1024);ByteBuffer[] bufferArray = { header, body };channel.read(buffers);
ByteBuffer header = ByteBuffer.allocate(128);ByteBuffer body = ByteBuffer.allocate(1024);//write data into buffersByteBuffer[] bufferArray = { header, body };channel.write(buffers);
RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");FileChannel fromChannel = fromFile.getChannel();RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");FileChannel toChannel = toFile.getChannel();long position = 0;long count = fromChannel.size();toChannel.transferFrom(fromChannel, position, count);
RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");FileChannel fromChannel = fromFile.getChannel();RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");FileChannel toChannel = toFile.getChannel();long position = 0;long count = fromChannel.size();fromChannel.transferTo(position, count, toChannel);
Selector组件可以运行判断多个Channel,动态决定使用哪个Channel来执行Read 或者 Write操作。通过这个组件可以上线一个Thread 管理多个Channels 或者 多个网络连接Channel。
通过使用Selector.open()方法来创建一个Selector
Selector selector = Selector.open();
为了能让Selector管理Channels需要调用Selector.register()注册到Selector
channel.configureBlocking(false); //The Channel must be in non-blocking mode to be used with a Selector
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
注册Channel的时候需要制定Channel需要关心的事件,事件包括:
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; 通过int interestSet = selectionKey.interestOps(); 可以得到所有Selector’s的事件。Simple Demo:
Selector selector = Selector.open();channel.configureBlocking(false);SelectionKey key = channel.register(selector, SelectionKey.OP_READ);while(true) {int readyChannels = selector.select();if(readyChannels == 0) continue;Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = selectedKeys.iterator();while(keyIterator.hasNext()) {SelectionKey key = keyIterator.next();if(key.isAcceptable()) {// a connection was accepted by a ServerSocketChannel.} else if (key.isConnectable()) {// a connection was established with a remote server.} else if (key.isReadable()) {// a channel is ready for reading} else if (key.isWritable()) {// a channel is ready for writing}keyIterator.remove();}}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/yxp20092010/article/details/46916461