泛谈Java NIO

前言

非阻塞IO,也被称之为新IO,它重新定义了一些概念。

1.缓冲buffer

2.通道 channel

3.通道选择器

BIO 阻塞IO,几乎所有的java程序员都会的字节流,字符流,输入流,输出流等分类就是针对BIO而言的。我们在使用BIO的时候都是建立基本的节点流然后用过滤流进行包装。

不同于BIO,NIO所有的IO操作都是通过通道读写buffer完成的。数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

通道

NIO的通道类似流,但是有所不同。

1.既可以从通道中读取数据,又可以写数据到通道。而流的读写通常是单向的

2.通道就是类似与高速路,数据通过buffer传递。通道负责从buffer中读,或者写入buffer

3.通道可以异步读写

  • FileChannel 从文件中读写数据
  • DatagramChannel 能通过UDP读写网络中的数据
  • SocketChannel 能通过TCP读写网络中的数据
  • ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel

Buffer

Buffer 用来缓存数据,NIO中所有的操作都是基于缓冲区继续操作的,所有的读写操作都是通过缓存区来进行完成。缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。

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

缓冲区基本属性

  • 容量 (capacity):表示 Buffer 最大数据容量,缓冲区容量不能为负,并且创建后不能更改。
  • 限制 (limit)
  • 位置 (position)

position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity都代表容量。

Buffer有一个固定的大小值,叫“capacity”。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。

写模式

当你写数据到Buffer中时,position表示当前的位置。初始的position值为0,当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1。在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。

读模式

当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0。当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值等于在写模式下position)。

使用

使用Buffer读写数据一般遵循以下四个步骤:

1.写入数据到Buffer

2.调用flip()方法

3.从Buffer中读取数据

4.调用clear()方法或者compact()方法

当向buffer写入数据时,buffer会记录下写了多少数据。一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式。在读模式下,可以读取之前写入到buffer的所有数据。

一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用clear()或compact()方法。clear()方法会清空整个缓冲区。compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。

使用案例如下:

import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
public class TestNio {
public static void main(String[] args) throws Exception {
/*FileOutputStream outputStream = new FileOutputStream("E:/i.txt");
FileChannel channel = outputStream.getChannel();
ByteBuffer buffer = ByteBuffer.wrap("hahahah".getBytes());
channel.write(buffer);
channel.close();*/
FileInputStream inputStream = new FileInputStream("E:/i.txt");
FileChannel channel = inputStream.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(10);

while (true){
// 读数据写入buffer 如果读了6个数据 那么positon limit均为6
int read = channel.read(buffer);
if(read == -1) break;
// 把position设置为0 写操作变为读操作(相对与buffer而言)
buffer.flip();
// hasRemaining当 position和limit相等的时候为false
while (buffer.hasRemaining()){
byte b = buffer.get();
System.out.println((char)b);
}
// clear实际上是positon 和 limit均置为0 数据实际上是未清楚的
// 读操作变为写操作(相对与buffer)
buffer.clear();
}
channel.close();
ByteBuffer wrap = new ByteBuffer.wrap("哈哈哈".getBytes());
// 编码处理
Charset gbk = Charset.forName("GBK");
ByteBuffer encode = gbk.encode("哈哈哈");
}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解java nio中的select和channel

    什么是NIO? 线程在处理数据时,如果线程还处于将数据从channel读到buffer的这段时间内,线程可以去做别的事情,等数据都读到buffer了,线程再回来处理读到的数据 channel是什么? 类比流的概念.与流的区别在于 1.channel是可读可写的,但是一个流要么写要么读 2.chanel可以异步的读和写 3.数据总是从channel中读到buffer,或者从buffer中写到channel 流的读取或写一般是一次性的操作,数据在读取过程中不会有缓存,这也就意味着没有办法自己随便移动

  • java8中NIO缓冲区(Buffer)的数据存储详解

    java8新特性NIO缓冲区(Buffer)的数据存储. ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer, DoubleBuffer. 1.缓冲区在java nio中负责数据的存储.缓冲区就是数组.用于存储不同数据类型的数据.根据数据类型不同(boolean除外),提供了相应类型的缓冲区. ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatB

  • 浅谈Java中BIO、NIO和AIO的区别和应用场景

    最近一直在准备面试,为了使自己的Java水平更上一个档次,拜读了李林峰老师的<Netty权威指南>,了解了Java关于IO的发展和最新的技术,真是受益匪浅,现在把我总结的关于BIO.NIO和AIO的区别和应用场景概述一遍. 在此之前,先弄清几个概念: 1.同步:使用同步IO时,Java自己处理IO读写. 2.异步:使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS,完成后OS通知Java处理(回调). 3.阻塞:使用阻塞IO时,Java调用会一直阻塞到读写完成

  • 泛谈Java NIO

    前言 非阻塞IO,也被称之为新IO,它重新定义了一些概念. 1.缓冲buffer 2.通道 channel 3.通道选择器 BIO 阻塞IO,几乎所有的java程序员都会的字节流,字符流,输入流,输出流等分类就是针对BIO而言的.我们在使用BIO的时候都是建立基本的节点流然后用过滤流进行包装. 不同于BIO,NIO所有的IO操作都是通过通道读写buffer完成的.数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中. 通道 NIO的通道类似流,但是有所不同. 1.既可以从通道中读取数据,又可以

  • java NIO 详解

    Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中. Asynchronous IO(异步IO):Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情.当数据被写入到缓冲区时,线程可以继续处理它.从缓冲区写入通道也类似. S

  • Java NIO和IO的区别

    下表总结了Java NIO和IO之间的主要差别,我会更详细地描述表中每部分的差异. 复制代码 代码如下: IO                NIO面向流            面向缓冲阻塞IO            非阻塞IO无                选择器 面向流与面向缓冲 Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的. Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方.此外,它不能前后移动流中的数

  • java nio基础使用示例

    在jdk1.4中提出的技术,非阻塞IO,采用的是基于事件处理方式.传统的io技术为阻塞的,比如读一个文件,惹read方法是阻塞的,直到有数据读入.归纳为:1.java io为阻塞,在打开一个io通道后,read将一直等待在端口一边读取字节内容,如果没有内容进来,read相当于阻塞掉了.2.在1的基础上改进为,开设线程,serversocker.accept()后让线程去等待,但是当并发量高的时候,相当耗费资源的.3.java nio为非阻塞,采用的是reactor反应堆模式,或者说observe

  • Java NIO原理图文分析及代码实现

    前言: 最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.可以参考:http://baike.baidu.com/view/32726.htm )机制时,发现hadoop的RPC机制的实现主要用到了两个技术:动态代理(动态代理可以参考博客:http://weixiaolu.iteye.com/blog/1477774 )和java NIO.为了能够正确地分析

  • Java NIO:浅析IO模型_动力节点Java学院整理

    也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗.在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型.下面本文先从同步和异步的概念 说起,然后接着阐述了阻塞和非阻塞的区别,接着介绍了阻塞IO和非阻塞IO的区别,然后介绍了同步IO和异步IO的区别,接下来介绍了5种IO模型,最后介绍了两种和高性能IO设计相关的设计模式(Reactor和Proactor). 以下是本文的目录大纲: 一.什么是同步?什么是异步? 二.什么是阻塞?什么是非阻塞

  • 支撑Java NIO与NodeJS的底层技术

    支撑Java NIO 与 NodeJS的底层技术 众所周知在近几个版本的Java中增加了一些对Java NIO.NIO2的支持,与此同时NodeJS技术栈中最为人称道的优势之一就是其高性能IO,那么我们今天要讨论的话题就是支撑这些技术的底层技术. 开始之前先要提出的一个问题是: 为什么NodeJS和Java NIO2没有在更早的时间出现? 答案:个人认为是底层的支撑技术还不成熟. 那么,底层技术指的是什么呢?对的,我想很多人已经猜到,是操作系统技术.本文提出的两个概念Java NIO2和Node

  • Java NIO实例UDP发送接收数据代码分享

    Java的NIO包中,有一个专门用于发送UDP数据包的类:DatagramChannel,UDP是一种无连接的网络协议, 一般用于发送一些准确度要求不太高的数据等. 完整的服务端程序如下: public class StatisticsServer { //每次发送接收的数据包大小 private final int MAX_BUFF_SIZE = 1024 * 10; //服务端监听端口,客户端也通过该端口发送数据 private int port; private DatagramChann

  • JDK1.7 之java.nio.file.Files 读取文件仅需一行代码实现

    JDK1.7中引入了新的文件操作类java.nio.file这个包,其中有个Files类它包含了很多有用的方法来操作文件,比如检查文件是否为隐藏文件,或者是检查文件是否为只读文件.开发者还可以使用Files.readAllBytes(Path)方法把整个文件读入内存,此方法返回一个字节数组,还可以把结果传递给String的构造器,以便创建字符串输出.此方法确保了当读入文件的所有字节内容时,无论是否出现IO异常或其它的未检查异常,资源都会关闭.这意味着在读文件到最后的块内容后,无需关闭文件.要注意

  • Java NIO Path接口和Files类配合操作文件的实例

    Path接口 1.Path表示的是一个目录名序列,其后还可以跟着一个文件名,路径中第一个部件是根部件时就是绝对路径,例如 / 或 C:\ ,而允许访问的根部件取决于文件系统: 2.以根部件开始的路径是绝对路径,否则就是相对路径: 3.静态的Paths.get方法接受一个或多个字符串,字符串之间自动使用默认文件系统的路径分隔符连接起来(Unix是 /,Windows是 \ ),这就解决了跨平台的问题,接着解析连接起来的结果,如果不是合法路径就抛出InvalidPathException异常,否则就

随机推荐