使用NIO主要就是为了提升IO的速度html
从文件中读取
与传统IO不一样的是,使用NIO从文件中读取主要分为三步:
(1)从FileInputStream中获取channel;java
FileInputStream fin = new FileInputStream( "readandshow.txt" ); FileChannel fc = fin.getChannel();
(2)建立buffer;数组
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
(3)将数据从channel读到buffer中。服务器
fc.read( buffer );
写入文件
相似的,利用NIO写入文件也分为三步:
(1)从FileInputStream中获取channel;网络
FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" ); FileChannel fc = fout.getChannel();
(2)建立一个缓冲区并在其中放入一些数据;函数
ByteBuffer buffer = ByteBuffer.allocate( 1024 ); for (int i=0; i<message.length; ++i) { buffer.put( message[i] ); //从message数组中取出放入buffer } buffer.flip(); //将buffer由写模式切换为读模式
(3)将数据从buffer写到通道中。学习
fc.write( buffer );
public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }
这里能够注意到limit,position和mark三个变量
(1) capacity:代表能够储存在缓冲区中的最大数据容量。
(2) position:下一个可插入的位置(写buffer时)或者下一个可读的位置(读buffer时)。
(3) limit:最多能写多少数据(写buffer时,至关于capacity),能够读多少数据(在从通道读入缓冲区时)。
(4) mark:标记,记录当前position的位置,能够经过reset()恢复到mark的位置。大数据
Selector selector = Selector.open();
this
channel.configureBlocking(false);
//使用selector必须保证channel是非阻塞的模式SelectionKey key = channel.register(selector, Selectionkey.OP_READ);
注意register的第二个参数表示对选择器对什么事件感兴趣。
而返回值记录了包括channel,buffer,interest集合和ready集合等。spa
示例程序
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 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(); //须要本身移除处理完的通道 } }
NIO具有必定的优势,但并非说传统IO就一无可取
(1)在处理数据上,若是遇到逐行处理的状况,如:
Name: Anna Age: 25 Email: anna@mailserver.com Phone: 1234567890
传统的IO能够这样写:
BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String nameLine = reader.readLine(); String ageLine = reader.readLine(); String emailLine = reader.readLine(); String phoneLine = reader.readLine();
但若是使用NIO:
ByteBuffer buffer = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buffer);
你就不知道缓冲区内是否恰好是一行数据,这样处理起来会比较麻烦。
(2)若是须要管理同时打开的成千上万个链接,这些链接每次只是发送少许的数据,例如聊天服务器,实现NIO的服务器多是一个优点。
若是你须要维持许多打开的链接到其余计算机上,如P2P网络中,使用一个单独的线程来管理你全部出站链接,多是一个优点。
但若是你有少许的链接使用很是高的带宽,一次发送大量的数据,也许典型的IO服务器实现可能很是契合。
学习参考:http://ifeve.com/java-nio-all/ Java NIO 系列教程
https://www.ibm.com/developer... NIO入门