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 buffer
int
bytesRead = inChannel.read(buf);
while(bytesRead!=-1){
System.out.println("Read
" + bytesRead);
//swither
buffer type to read data from buffer
buf.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 byte
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
while(bytesRead!=-1){
buf.flip(); //make buffer ready for read
while(buf.hasRemaining()){
System.out.print((char) buf.get()); // read 1 byte at a time
}
buf.clear(); //make buffer ready for writing
bytesRead = 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 buffers
ByteBuffer[] 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