NIO基本操作
NIO是Java 4里面提供的新的API,目的是用来解决传统IO的问题
NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器)
Channel(通道)
通道:类似于流,但是可以异步读写数据(流只能同步读写),通道是双向的,(流是单向的),通道的数据总是要先读到一个buffer 或者 从一个buffer写入,即通道与buffer进行数据交互。
通道类型:
FileChannel:从文件中读写数据。
DatagramChannel:能通过UDP读写网络中的数据。
SocketChannel:能通过TCP读写网络中的数据。
ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
通过使用FileChannel可以从文件读或者向文件写入数据;通过SocketChannel,以TCP来向网络连接的两端读写数据;通过ServerSocketChanel能够监听客户端发起的TCP连接,并为每个TCP连接创建一个新的SocketChannel来进行数据读写;通过DatagramChannel,以UDP协议来向网络连接的两端读写数据。
Buffer(缓冲区)
缓冲区 本质上是一块可以存储数据的内存,被封装成了buffer对象而已!
缓冲区类型:
ByteBuffer
MappedByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
常用方法:
allocate() - 分配一块缓冲区
put() - 向缓冲区写数据
get() - 向缓冲区读数据
filp() - 将缓冲区从写模式切换到读模式
clear() - 从读模式切换到写模式,不会清空数据,但后续写数据会覆盖原来的数据,即使有部分数据没有读,也会被遗忘;
compact() - 从读数据切换到写模式,数据不会被清空,会将所有未读的数据copy到缓冲区头部,后续写数据不会覆盖,而是在这些数据之后写数据
mark() - 对position做出标记,配合reset使用
reset() - 将position置为标记值
hasRemaining() - 判断是否还有可用数据
缓冲区的一些属性:
capacity - 缓冲区大小,无论是读模式还是写模式,此属性值不会变;
position - 写数据时,position表示当前写的位置,每写一个数据,会向下移动一个数据单元,初始为0;最大为capacity - 1切换到读模式时,position会被置为0,表示当前读的位置
limit - 写模式下,limit 相当于capacity 表示最多可以写多少数据,切换到读模式时,limit 等于原先的position,表示最多可以读多少数据。
Selector(选择器)
选择器:相当于一个观察者,用来监听通道感兴趣的事件,一个选择器可以绑定多个通道;
通道向选择器注册时,需要指定感兴趣的事件,选择器支持以下事件:
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE
如果你对不止一种事件感兴趣,那么可以用“位或”操作符将常量连接起来,如下:
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
通道向选择器注册时,会返回一个 SelectionKey对象,具有如下属性
interest集合
ready集合
Channel
Selector
附加的对象(可选)
用“位与”操作interest 集合和给定的SelectionKey常量,可以确定某个确定的事件是否在interest 集合中。
int interestSet = selectionKey.interestOps(); boolean isInterestedInAccept = interestSet & SelectionKey.OP_ACCEPT;
boolean isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;
boolean isInterestedInRead = interestSet & SelectionKey.OP_READ;
boolean isInterestedInWrite = interestSet & SelectionKey.OP_WRITE;
ready 集合是通道已经准备就绪的操作的集合。在一次选择(Selection)之后,你会首先访问这个ready set。Selection将在下一小节进行解释。可以这样访问ready集合:
int readySet = selectionKey.readyOps();
也可以使用以下四个方法获取已就绪事件,返回值为boolean:
selectionKey.isAcceptable();
selectionKey.isConnectable();
selectionKey.isReadable();
selectionKey.isWritable();
可以将一个对象或者更多信息附着到SelectionKey上,即记录在附加对象上,方法如下:
selectionKey.attach(theObject);
Object attachedObj = selectionKey.attachment();
可以通过选择器的select方法获取是否有就绪的通道;
int select()
int select(long timeout)
int selectNow()
返回值表示上次执行select之后,就绪通道的个数。
可以通过selectedKeySet获取已就绪的通道。返回值是SelectionKey 的集合,处理完相应的通道之后,需要removed 因为Selector不会自己removed
select阻塞后,可以用wakeup唤醒;执行wakeup时,如果没有阻塞的select 那么执行完wakeup后下一个执行select就会立即返回。
调用close() 方法关闭selector
传统IO和NIO简单例子
传统IO读取文件:
public static void ioRead() {
File file = new File("f:/io.txt");
InputStream in = null;
try {
in = new FileInputStream(file);
byte[] bytes = new byte[1024];
in.read(bytes);
System.out.println(new String(bytes)); } catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
NIO操作
public static void nioRead() {
RandomAccessFile aFile = null;
try {
aFile = new RandomAccessFile("F:/io.txt", "rw");
FileChannel fileChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
int bytesRead = fileChannel.read(buf);
System.out.println(bytesRead);
while (bytesRead != -1) {
buf.flip();
while (buf.hasRemaining()) {
System.out.print((char) buf.get());
}
buf.compact();
bytesRead = fileChannel.read(buf);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (aFile != null) {
aFile.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
NIO基本操作的更多相关文章
- Java IO系列之二:NIO基本操作
核心部分 NIO( New Input/ Output) , 引入了一种基于通道和缓冲区的 I/O 方式,NIO 是一种同步非阻塞的 IO 模型.同步是指线程不断轮询 IO 事件是否就绪,非阻塞是指 ...
- 撸基础篇系列,JAVA的NIO部分
前言:撸基础篇系列,避免每次都要从头开始看,写个自己的知识体系树 NIO 核心就是异步, 比如,复制文件,让操作系统去处理,等通知 BIO核心类 一,BIO NIO基本操作类 Bytebuffer 构 ...
- NIO缓冲区基本操作:rewind(),clear(),flip()
rewind() rewind()方法将position置0,清除mark,它的作用在于为提取Buffer的有效数据做准备. ByteBuffer byteBuf = ByteBuffer.alloc ...
- Java NIO教程 Selector
这次我们开讲非阻塞I/O中的Selector,它需要配合非阻塞的TCP和UDP来使用.首先我们先简单讲一下TCP和UDP的非阻塞通道. 非阻塞I/O通道 在上代码前我们先讲解一些最基本的知识.TCP和 ...
- Java NIO教程 文件系统
在NIO.2的文件系统中,Path是一切操作的基础.Path准确来说,代表着文件系统中的位置.可以代表一个目录(也就是通常所说的文件夹),也可以代表一个文件. 在新文件系统中,还有一个不得不说的就是F ...
- Java NIO中的读和写
一.概述 读和写是I/O的基本过程.从一个通道中读取只需创建一个缓冲区,然后让通道将数据读到这个缓冲区.写入的过程是创建一个缓冲区,用数据填充它,然后让通道用这些数据来执行写入操作. 二.从文件中读取 ...
- Java NIO入门
NIO入门 前段时间在公司里处理一些大的数据,并对其进行分词.提取关键字等.虽说任务基本完成了(效果也不是特别好),对于Java还没入门的我来说前前后后花了2周的时间,我自己也是醉了.当然也有涉及到机 ...
- java nio io模型
I/O模型 在开始NIO的学习之前,先对I/O的模型有一个理解,这对NIO的学习是绝对有好处的.我画一张图,简单表示一下数据从外部磁盘向运行中进程的内存区域移动的过程: 这张图片明显忽略了很多细节,只 ...
- Java NIO 内存映射文件
Java NIO 内存映射文件 @author ixenos 文件操作的四大方法 前提:内存的访问速度比磁盘高几个数量级,但是基本的IO操作是直接调用native方法获得驱动和磁盘交互的,IO速度限制 ...
随机推荐
- easyui的DataGrid的单元格添加ProgressBar进度条
网上的搜到的好多不能用,官方easy-ui使用进度条 <div id="p" class="easyui-progressbar" ></di ...
- sql ''增删改'' 笔记
结构语言分类 DDL(数据定义语言) create drop alter 创建删除以及修改数据库,表,存储过程,触发器,索引.... DML(数据操作语言) insert delete ...
- 20155208实验二 Java面向对象程序设计
20155208实验二 Java面向对象程序设计 一.实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装.继承.多态 3.初步掌握UML建模 4.熟悉S.O.L.I.D原则 5 ...
- 20155208徐子涵 2016-2017-2 《Java程序设计》第6周学习总结
20155208徐子涵 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 10.1.1 1.Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串 ...
- tcp面试题
常见面试题[问题1]为什么连接的时候是三次握手,关闭的时候却是四次握手? 答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文.其中ACK报文是用来应答的, ...
- 【挑战赛16A】【取石子】【组合数学】
链接:https://www.nowcoder.com/acm/contest/113/A 来源:牛客网 取石子时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K,其他语言5 ...
- 【BZOJ3992】【SDOI2015】序列统计
数论劲啊 原题: 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列.但是小 ...
- gvim最简化设置,去掉工具栏和菜单栏
编辑vimrc文件(该文件位于gvim安装目录下),在文件末尾添加以下语句即可 set gfn=Courier_New:h14colorscheme torteset guioptions-=mset ...
- linux内核编程helloworld(中级)
传入参数 [root@bogon modules]# cat first.c #include<linux/kernel.h> #include<linux/stat.h> # ...
- centos7升级自带的php5.4版本到php5.6
history命令历史 8 yum provides php #自带的只有5.4版本 9 rpm -Uvh https://mirror.webtatic.com/yum/el7/epel-relea ...