程序员的资源宝库

网站首页 > gitee 正文

NIO(一)

sanyeah 2024-04-05 13:12:14 gitee 7 ℃ 0 评论

1 NIO简介

Java NIO (New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。

2 NIO与IO的区别

IO NIO
面向流 面向缓冲区
阻塞IO 非阻塞IO
选择器(selectors)

IO是单向的,输入流:数据从文件/磁盘/网络到程序。

3 通道和缓冲区

Java NIO系统的核心在于:通道(Channel)和缓冲区(Buffer)。通道表示打开到IO设备(例如:文件、套接字)的连接。若需要使用NIO系统,需要获取用于连接IO设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理。

简而言之,通道负责传输,缓冲区负责存储。

3.1 缓冲区

  • 缓冲区(Buffer):一个用于特定基本数据类型的容器。由 java.nio包定义的,所有缓冲区都是 Buffer抽象类的子类。
  • Java NIO中的Buffer主要用于与NIO通道进行交互,数据是从通道读入缓冲区,从缓冲区写入通道中的。

4 缓冲区的数据存取

缓冲区在Java NIO中负责数据的存取。

缓冲区就是数组,用于存储不同数据类型的数据。根据数据类型的不同(boolean除外),提供了相应类型的缓冲区:ByteBuffer、 CharBuffer、 ShotBuffer、 IntBuffer、 LongBuffer、 FloatBuffer、 DoubleBuffer。上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区。

// 分配一个指定大小的缓冲区
// ByteBuffer继承自Buffer,Buffer核心属性
ByteBuffer buff = ByteBuffer.allocate(1024);

4.1 Buffer的四个核心属性

private int mark = -1;
private int position = 0;
private int limit;
private int capacity;

position:位置,表示缓冲区中正在操作数据的位置;

limit:界限,表示缓冲区中可以操作数据的大小,大于limit的数据不能进行读写;

capacity:容量,表示缓冲区中最大存储数据的容量,一旦声明不能该表。

mark:标记,表示记录当前position的位置。可以通过reset()恢复到mark的位置。

mark <= position <= limit <= capacity

// 1.分配一个指定大小的缓冲区
ByteBuffer buff = ByteBuffer.allocate(1024);
System.out.println(buff.position());// 0
System.out.println(buff.limit());// 1024
System.out.println(buff.capacity());// 1024
// 2.利用put()存入数据到缓冲区
String str = "abcde";
buff.put(str.getBytes());
System.out.println(buff.position());// 5
System.out.println(buff.limit());// 1024
System.out.println(buff.capacity());// 1024
// 3.切换读取数据模式
buff.flip();
System.out.println(buff.position());// 0
System.out.println(buff.limit());// 5
System.out.println(buff.capacity());// 1024
// 4.利用get()读取缓冲区中的数据
byte[] bytes = new byte[buff.limit()];
buff.get(bytes);
System.out.println(new String(bytes, 0, bytes.length));// abcde
System.out.println(buff.position());// 5
System.out.println(buff.limit());// 5
System.out.println(buff.capacity());// 1024
// 5.rewind() 可重复读(回到了第3步)
buff.rewind();
System.out.println(buff.position());// 0
System.out.println(buff.limit());// 5
System.out.println(buff.capacity());// 1024
// 6.清空缓冲区(但是缓冲区中的数据依然存在,只是处于“被遗忘”状态)
buff.clear();
System.out.println(buff.position());// 0
System.out.println(buff.limit());// 1024 
System.out.println(buff.capacity());// 1024
System.out.println((char) buff.get());// a

上述第1、2、3步骤如图:

mark属性用法:

@Test
public void test2() {
    String str = "abcde";
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    buffer.put(str.getBytes());
    buffer.flip();
    byte[] bytes = new byte[buffer.limit()];
    buffer.get(bytes, 0, 2);
    System.out.println(buffer.position());// 2

    buffer.mark();// 标记

    buffer.get(bytes, 2, 2);
    System.out.println(buffer.position());// 4

    buffer.reset();// 恢复
    System.out.println(buffer.position());// 2

    // 判断缓冲区中是否还有剩余数据
    if (buffer.hasRemaining()) {
        // 获取缓冲区中可以操作的数量
        System.out.println(buffer.remaining());
    }
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表