文档章节

JAVA NIO编程入门(一)

木木匠
 木木匠
发布于 2018/09/01 21:39
字数 1482
阅读 189
收藏 9

JAVA NIO编程入门(一)

一、前言

笔者之前接触的NIO编程比较少,所以对这一块的基础也比较弱,NIO作为java编程中一个重要的模块,不能很好的掌握它,感觉自己在java方面就掌握的不够,所以,接下来,笔者会学习NIO编程,所以,该系列文章不会涉及到很深源码解析,纯粹的是学习课程,也可以理解为笔者的笔记,记录学习NIO的过程,同时也希望这类文章可以对同样想掌握NIO编程的你有帮助。

二、什么是NIO?

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为非阻塞模式。

三、IO和NIO的区别

  • IO是面向字节流和字符流的,而NIO是面向缓冲区的。
  • IO是阻塞模式的,NIO是非阻塞模式的
  • NIO新增了选择器的概念,可以通过选择器监听多个通道。

四、NIO相关概念

Channel(通道)

Java NIO的通道类似流,但又有些不同:

既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。 通道可以异步地读写。

通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。

 

 

Channel的实现

这些是Java NIO中最重要的通道的实现:

  • FileChannel: 从文件中读写数据。

  • DatagramChannel : 能通过UDP读写网络中的数据。

  • SocketChannel: 能通过TCP读写网络中的数据。

  • ServerSocketChannel :可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

Buffer(缓冲区)

缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。

Buffer(缓冲区)的主要属性

属性 功能
capacity 容量
position 缓冲区当前位置指针,最大可为capacity – 1
limit 缓冲区最大读取和写入限制

buffer属性示意图:

 

 

上图展示了写模式和读模式下,以上属性的示意图,写模式下,limit和capacity是一样的,这表示你能写入的最大容量数据,读模式下,limit会和position一样,表示你能读到写入的全部数据。

Buffer(缓冲区)的主要分类

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

其实以上基本上为了接收不同的数据类型而对应的,只有一个特殊的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。

结果和预期一样,我们完成了NIO编程输出磁盘文件内容,其实上面代码中,我第一印象有疑问的地方就是buf.flip(),其他只要用过IO的应该都能理解,既然不能理解我们就先调试下,注释掉该段内容,看看输出结果如何。

注释掉buf.flip()后,输出结果果真不对了,那究竟是为啥呢?

上图是第一个循环,我们可以看到缓冲区的position=10,limit=10,cap=10。调用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

推荐阅读

Java锁之ReentrantLock(一)

Java锁之ReentrantLock(二)

Java锁之ReentrantReadWriteLock

© 著作权归作者所有

下一篇: 位运算
木木匠

木木匠

粉丝 180
博文 32
码字总数 73479
作品 0
广州
高级程序员
私信 提问
少啰嗦!一分钟带你读懂Java的NIO和经典IO的区别

本文引用了“架构师社区”公众号的《史上讲的最好的Java NIO与IO的区别与应用》一文部分内容,感谢原作者的技术分享。 1、引言 很多初涉网络编程的程序员,在研究Java NIO(即异步IO)和经典...

JackJiang2011
06/25
0
0
JAVA NIO 编程入门(三)

一、前期回顾 上一篇文章JAVA NIO 编程入门(二)学习了NIO的聚集和分散,以及选择器的使用,并通过一个小demo进行实战,演示了如何进行分散和聚集,以及其主要使用场景,本文将是NIO编程入门...

木木匠
2018/09/16
67
0
JAVA NIO编程入门(二)

一、回顾 上一篇文章 JAVA NIO编程入门(一)我们学习了NIO编程的基础知识,并通过一个小demo实战帮助了解NIO编程的channel,buffer等概念。本文会继续学习JAVA NIO编程,并通过一个小示例来...

木木匠
2018/09/09
96
0
Java NIO系列教程(十六) Java NIO Files

原文地址 译者:章筱虎 java NIO Files类(java.nio.file.Files) 提供了操作文件的相关方法。本篇文章将会覆盖大多数常用的方法。Files类包含了很多方法,如果你需要的功能在文中没有提及,需...

章 筱虎
2018/01/23
0
0
Java程序员必读书单,家族又添新成员

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书。 ——异步小编 有些革命出其不意地吸引了全世界的眼球。Twitter、Linux操作系统和...

异步社区
2018/05/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

代理模式之JDK动态代理 — “JDK Dynamic Proxy“

动态代理的原理是什么? 所谓的动态代理,他是一个代理机制,代理机制可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成,通过代理可以有效的让调...

code-ortaerc
今天
4
0
学习记录(day05-标签操作、属性绑定、语句控制、数据绑定、事件绑定、案例用户登录)

[TOC] 1.1.1标签操作v-text&v-html v-text:会把data中绑定的数据值原样输出。 v-html:会把data中值输出,且会自动解析html代码 <!--可以将指定的内容显示到标签体中--><标签 v-text=""></......

庭前云落
今天
7
0
VMware vSphere的两种RDM磁盘

在VMware vSphere vCenter中创建虚拟机时,可以添加一种叫RDM的磁盘。 RDM - Raw Device Mapping,原始设备映射,那么,RDM磁盘是不是就可以称作为“原始设备映射磁盘”呢?这也是一种可以热...

大别阿郎
今天
10
0
【AngularJS学习笔记】02 小杂烩及学习总结

本文转载于:专业的前端网站☞【AngularJS学习笔记】02 小杂烩及学习总结 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy ......

前端老手
昨天
14
0
Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大...

阮鹏
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部