java NIO

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java NIO相关的知识,希望对你有一定的参考价值。

一、简介

1、I/O

I/O指的是计算机与外部世界,或者程序与计算机其他部分的接口,即输入/输出。

在JAVA中,通常都以流的方式完成I/O,通过一个Stream对象操作。这种操作方法是堵塞的,无法移动读取位置的(只能一直往下读,不能后退),并且效率较低。JAVA为了提高I/O效率,在1.4之后,推出了NIO。

2、NIO vs I/O

I/O NIO
面向流,一次读取一个或多个字节,在流中无法前后移动 面向缓存,读取的数据先统一放在缓存中,在缓存中能前后移动
堵塞,从流读取数据时,线程无法做其他事情 非堵塞,数据还未完整读取到缓存中时,线程可以先做其他事
一对一:一条线程负责一个数据操作任务 一对多,一条线程负责多个数据操作任务

 

 

 

二、主要概念

NIO要实现面向缓存的非堵塞数据读取,依赖"Channel(通道)"和"Buffer(缓冲区)";

NIO要实现一条线程管理多个数据操作,依赖"Selector(选择器)"。

1、Channel通道

定义

A channel represents an open connection to an entity such as a hardware device, a file, a network socket, or a program component that is capable of performing one or more distinct I/O operations, for example reading or writing.

即通过Channel,你可以和外部进行数据的读写。

虽然NIO的Channel和I/O的stream很像,不过还是有区别的:

  • Channel总是面向缓存的,而流既可以一次读取一个或多个字节,也可以选择先把数据读到缓存中。
  • Channel可读也可写,流只能读或者写。
  • Channel可以异步读写

类型

根据Channel数据来源不同,Channel有不同的实现:

  • FileChannel : A channel for reading, writing, mapping, and manipulating a file -> 用于文件的读写
  • DatagramChannel : A selectable channel for datagram-oriented sockets -> 用于UDP的数据读写
  • SocketChannel : A selectable channel for stream-oriented connecting sockets -> 用于TCP的数据读写
  • ServerSocketChannel : A selectable channel for stream-oriented listening sockets -> 用于监听TCP连接请求,为每个请求再建立一个SocketChannel

I/O 和 NIO 数据操作对比

// I/O流操作
FileInputStream inputStream = new FileInputStream("io.txt");
byte[] data = new byte[1024];
while(inputStream.read(data) != -1){
    // 从流中读取多个字节,进行操作
}

 

// NIO channel操作
// 从文件流中获取channel
FileInputStream inputStream = new FileInputStream("nio.txt");
FileChannel fileChannel = inputStream.getChannel();

// 新建缓存,用于存放Channel读取的数据
ByteBuffer buffer = ByteBuffer.allocate(1024);

// 通过Channel读取数据到缓存中
fileChannel.read(buffer);

Channel间数据传输

对于FileChannel之间,利用transferFrom和transferTo可以直接进行数据传输,提高性能。

将fromChannel中数据传输到toChannel 中,position指toChannel中开始的位置,count指接收的数据:

toChannel.transferFrom(fromChannel, position, count) 或

fromChannel.transferTo(position, count, toChannel)

2、buffer缓冲区

定义

A container for data of a specific primitive type.

A buffer is a linear, finite sequence of elements of a specific primitive type.  Aside from its content, the essential properties of a buffer are its capacity, limit, and position.

buffer缓冲区是一块内存,用于存放原始类型数据。它的特点是:线性,有限,有序,只能存一种原始类型数据

属性

  • capacity : A buffer‘s capacity is the number of elements it contains. -> 缓冲区大小
  • limit : A buffer‘s limit is the index of the first element that should not be read or written. -> 用于标记读写的边界。读模式,limit表示目前缓冲区内存放的数据量。写模式,limit表示缓冲区最大的存放数,等于capacity.
  • position: A buffer‘s position is the index of the next element to be read or written. -> 标记目前读或写的位置

技术分享

类型

根据buffer中存放的原始类型不同,有以下几种Buffer实现

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

基本用法

  • 调用allocate()分配大小
  • channel写数据到buffer
  • 调用flip()  -> buffer默认是写模式,当要从Buffer中读数据时,需要手动调flip方法,转为读模式。(这时,limit置为position,position置为0)
  • 从buffer中读数据
  • 当要重新往buffer中写数据时,需要调用clear()或compact方法。

其他方法介绍

  • clear : 将position置为0, limit置为capacity,清空buffer。对于还未读取的数据,直接丢失。
  • compact:先将未读的数据复制到缓存的开头,position置到未读数据的后一位,limit置为capacity。
  • rewind: 将position重置为0,这样我们可以重读Buffer数据
  • mark和reset:用mark标记此时的posiiton,之后移动position。调用reset,会将position重置为mark标记的地方。

3、

 

 

 

以上是关于java NIO的主要内容,如果未能解决你的问题,请参考以下文章

java.io.File 与 java.nio.Files 哪个是新代码中的首选?

Java NIO

Java NIO6:选择器2---代码篇

Java NIO6:选择器2---代码篇

java----IO和NIO的区别

Java IO之NIO原理解析以及代码解析