Java NIO 学习总结
1.Java NIO 核心组成部份:
2.Buffer1.基本用法(4个步骤):写入数据到Buffer. 2.Buffer的分配ByteBBuffer buf = ByteBuffer.allocate(48); 3.向Buffer中写数据写数据到Buffer的两种方式: int bytesRead = inChannel.write(buf); 通过put方法写Buffer的例子: buf.put(127); 4. flip()方法flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。 5.从Buffer中读取数据从Buffer中读取数据有两种方式:
6. rewind()方法Buffer.rewind()将position设回0,所以你可以重读Buffer中的所有数据。limit保持不变,依然表示能从Buffer中读取多少个元素(byte、char等). 7.mark和reset()方法通过调用Buffer.mark()方法,可以标记Buffer中的1个特定position。以后可以通过调用Buffer.reset()方法恢复到这个position。 buffer.mark();
//call buffer.get();
buffer.reset(); 8.equals()当满足以下条件时,表示两个Buffer相等: 9.compareTo()方法compareTo()方法比较两个Buffer的剩余元素(byte,char),如果满足以下条件,则认为1个Buffer小于另外1个Buffer 10. scatter/gather.
11.transferForm()FileChannel的transferFrom()方法可以将数据从源通道传输到FileChannel中. public class FileChannelTest {
public static void main(String[] args) {
try{
RandomAccessFile fromFile = new RandomAccessFile("1.cpp","rw");
FileChannel fromChannel = fromFile.getChannel();
RandomAccessFile tofile = new RandomAccessFile("fei.cpp","rw");
FileChannel toChannel = tofile.getChannel();
long position = 0;
long count = fromChannel.size();
toChannel.transferFrom(fromChannel,position,count);
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException t){
t.printStackTrace();
}
}
}
Selector 选择器Select(选择器)是Java NIO 中能够检测1到多个NIO通道,并能够知晓通道是不是为诸如读写事件做好准备的组件,这样,1个单独的线程就能够管理多个channel,从而管理多个网络连接. 1.通过调用Selector.open()方法创建1个Selector,以下:
2.向Selector注册通道
与Selector1起使用时,Channel必须处于非阻塞模式下,这意味着不能将FileChannel与Selector1起使用,由于FileChannel不能切换到非阻塞模式,而套接字通道都可以. 3.SelectionKey当向Selector注册Channel时,register()方法会返回1个SelectionKey对象,这个对象包括1些你感兴趣的属性. 4.interest集合interest集合是你选择的感兴趣的事件集合,可以通过SelectionKey读写interest集合,像这样: int interestSet = selectionKey.interestOps();
boolean isInterestedInAccept = (interestSet & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT;
boolean isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;
boolean isInterestedInRead = interestSet & SelectionKey.OP_READ;
boolean isInterestedInWrite = interestSet & SelectionKey.OP_WRITE; 可以看到,用”位与”操作interest集合和给定的SelectionKey常量,可以肯定某个肯定的事件是不是在interest集合中. 5.ready集合ready 集合是通道已准备就绪的操作的集合。在1次选择(Selection)以后,你会首先访问这个ready set。Selection将在下1小节进行解释。可以这样访问ready集合:
可以像检测interest集合那样,来检测channel中甚么事件或操作已就绪,但是,也能够使用以下4个方法,它们都会返回1个布尔类型: selectionKey.isAcceptable();
selectionKey.isConnectable();
selectionKey.isReadable();
selectionKey.isWritable(); Channel + Selector Channel channel = selectionKey,channel();
Selector selector = selectionKey.selector(); 6.通过Selector选择通道1旦向Selector注册了1个或多个通道,就能够调用几个重载的select()方法,这些方法返回你所感兴趣的事件(如连接,接受,读或写)已准备就绪的那些通道,换句话说,如果你对”读就绪事件感兴趣”,select()方法会返回读事件已就绪的那些通道. Set selectedKeys = selector.selectedKeys();
Iterator 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();
} 这个循环遍历已选择键集中的每一个键,并检测各个键多对应的通道的就绪事件. SelectionKey.channel()方法返回的通道需要转型成你要处理的类型,如ServerSocketChannel或SocketChannel等。 7.FileChannel.FileChannel没法设置为非阻塞模式,它总是运行在阻塞模式下. RandomAccessFile aFile = new RandomAccessFile("1.txt","rw");
FileChannel inChannel = aFile.getChannel(); 2.从FileChannel读取数据 ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf); 3.向FileChannel写数据 String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()){
channel.write(buf);
}
注意FileChannel.write()是在while循环中调用的,由于没法保证write()方法1次能向FileChannel写入多少字节,因此需要重复调用write()方法,直到Buffer已没有还没有写入通道的字节. 4.关闭FileChannel
例子以下: long pos = channel.position();
channel.position(pos +123); 如果将位置设置在文件结束以后,然后试图从文件中读取数据,该方法将返回⑴—文件结束标志.
6.FileChannel的truncate方法
7.FileChannel的force方法 channel.force(true); 8.SocketChannelSocketChannel 是1个连接到TCP网络套接字的通道.可以通过以下两种方式创建SocketChannel: SocketChannel socketChannel =SocketChannel.open();
SocketChannel.connect(new InetSocketAddress(IP,80)); 2.关闭SocketChannel socketChannel.close(); 3.从SocketChannel读取数据 String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()){
channel.write(buf); 注意SocketChannel.write()方法的调用是在1个while循环中的。Write()方法没法保证能写多少字节到SocketChannel。所以,我们重复调用write()直到Buffer没有要写的字节为止。 socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress(IP,port));
while(!socketChannel.finishConnect()){
//wait,or do something else ...
} write() 9.ServerSocketChannelServerSocketChannel 是1个可以监听进来的TCP连接的通道,就像标准IO中的ServerSocket1样,ServerSocketChannel. ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
while(true){
SocketChannel socketChannel = serverSocketChannel.accept();
} 1.打开ServerSocketChannel ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); 2.关闭ServerSocketChannel ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
while(true){
SocketChannel socketChannel = serverSocketChannel.accept();
if(socketChannel != null){
//do something with socketChannel.
}
} 10 Pipe管道是2个线程之间的单向数据连接,Pipe有1个source通道和1个sink通道,数据会被写到sink通道,从source通道读取. Pipe pipe = Pipe.open(); 2.向管道中写数据 Pipe.SinkChannel sinkChannel = pipe.sink(); 通过调用SinkChannel的Write()方法,将数据写入到SinkChannel,像这样: String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()){
channel.write(buf); 3.从管道中读取数据 Pipe.SourceChannel sourceChannel = pipe.source();
ByteBuffer buf =ByteBuffer.allocate(48);
int bytesRead = sourceChannel.read(buf);
read()方法的返回值int会告知我们多少自己被读进了缓冲区. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |