笔者以前接触的NIO编程比较少,因此对这一块的基础也比较弱,NIO做为java编程中一个重要的模块,不能很好的掌握它,感受本身在java方面就掌握的不够,因此,接下来,笔者会学习NIO编程,因此,该系列文章不会涉及到很深源码解析,纯粹的是学习课程,也能够理解为笔者的笔记,记录学习NIO的过程,同时也但愿这类文章能够对一样想掌握NIO编程的你有帮助。html
Java NIO(New IO)是一个能够替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不一样的IO工做方式。NIO能够理解为非阻塞IO,传统的IO的read和write只能阻塞执行,线程在读写IO期间不能干其余事情,好比调用socket.read()时,若是服务器一直没有数据传输过来,线程就一直阻塞,而NIO中能够配置socket为非阻塞模式。java
Channel(通道)编程
Java NIO的通道相似流,但又有些不一样:bash
既能够从通道中读取数据,又能够写数据到通道。但流的读写一般是单向的。 通道能够异步地读写。服务器
通道中的数据老是要先读到一个Buffer,或者老是要从一个Buffer中写入。网络
Channel的实现app
这些是Java NIO中最重要的通道的实现:dom
FileChannel: 从文件中读写数据。异步
DatagramChannel : 能经过UDP读写网络中的数据。socket
SocketChannel: 能经过TCP读写网络中的数据。
ServerSocketChannel :能够监听新进来的TCP链接,像Web服务器那样。对每个新进来的链接都会建立一个SocketChannel。
Buffer(缓冲区)
缓冲区本质上是一块能够写入数据,而后能够从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。
Buffer(缓冲区)的主要属性
属性 | 功能 |
---|---|
capacity | 容量 |
position | 缓冲区当前位置指针,最大可为capacity – 1 |
limit | 缓冲区最大读取和写入限制 |
buffer属性示意图:
上图展现了写模式和读模式下,以上属性的示意图,写模式下,limit和capacity是同样的,这表示你能写入的最大容量数据,读模式下,limit会和position同样,表示你能读到写入的所有数据。
Buffer(缓冲区)的主要分类
其实以上基本上为了接收不一样的数据类型而对应的,只有一个特殊的MappedByteBuffer,本次先不学习它,后续再去了解它。
咱们主要以理解上面介绍的概念为目的实现一个简单的NIO编程,读取文件夹内的文件,而后输出到控制台。
public static void testNio(){
try {
RandomAccessFile rdf=new RandomAccessFile("E:\\nio\\niotest.txt","rw");
//利用channel中的FileChannel来实现文件的读取
FileChannel inChannel= rdf.getChannel();
//设置缓冲区容量为10
ByteBuffer buf= ByteBuffer.allocate(10);
//从通道中读取数据到缓冲区,返回读取的字节数量
int byteRead=inChannel.read(buf);
//数量为-1表示读取完毕。
while (byteRead!=-1){
//切换模式为读模式,其实就是把postion位置设置为0,能够从0开始读取
buf.flip();
//若是缓冲区还有数据
while (buf.hasRemaining()){
//输出一个字符
System.out.print((char) buf.get());
}
//数据读完后清空缓冲区
buf.clear();
//继续把通道内剩余数据写入缓冲区
byteRead = inChannel.read(buf);
}
//关闭通道
rdf.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
复制代码
我在磁盘中niotest.txt的内容是hello world,咱们看看运行结果是否是hello world。
buf.flip()
,其余只要用过IO的应该都能理解,既然不能理解咱们就先调试下,注释掉该段内容,看看输出结果如何。
注释掉buf.flip()
后,输出结果果然不对了,那到底是为啥呢?
buf.hasRemaining()
为false,因此buffer第一次没有输出任何东西。看看第二次循环
buffer读取了10字节内容,内容就是:hello worl。
buf.hasRemaining() 判断为false,直接清空buffer(直接把position复位为0,能够直接覆盖内容),读取剩下内容。
最后只剩下一个字符 d
读取,这个时候读取完后,buffer内容以下:dello worl。
最后输出由于从postion=1位置输出,因此输出:ello worl。
根据以上解析,咱们发现注释了buf.flip()后,position位置写入是什么位置,读出就是什么位置,因此,该方法应该就是把position赋值为0,从开始读取。解读源码也证明了个人猜测,源码以下:
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
复制代码
《JAVA NIO》