一、java基础之nio编程

一、什么是nio

1.NIO是一个可以替代标准Java IO API的IO API(从Java 1.4开始),NIO提供了与标准IO不同的IO工作方式,NIO: Channels and Buffers(通道和缓冲区)

二、nio与io的对比

IO

NIO

面向流

面向缓冲区

阻塞IO

阻塞IO

选择器

 

三、buffer的数据存取

1.Java NIO中的Buffer主要用于与NIO通道进行交互,数据是从通道读入到缓冲区,从缓冲区写入通道中的,Buffer就像一个数组,可以保存多个相同类型的数据。根据类型不同(boolean除外),有以下Buffer常用子类:

ByteBuffer

CharBuffer

ShortBuffer

IntBuffer

LongBuffer

FloatBuffer

DoubleBuffer

2.buffer的概述

1)容量(capacity):表示Buffer最大数据容量,缓冲区容量不能为负,并且建立后不能修改。

2)限制(limit):第一个不应该读取或者写入的数据的索引,即位于limit后的数据不可以读写。缓冲区的限制不能为负,并且不能大于其容量(capacity)。

3)位置(position):下一个要读取或写入的数据的索引。缓冲区的位置不能为负,并且不能大于其限制(limit)。

4)标记(mark)与重置(reset):标记是一个索引,通过Buffer中的mark()方法指定Buffer中一个特定的position,之后可以通过调用reset()方法恢复到这个position。

3.代码

/**
 * (缓冲区)buffer 用于NIO存储数据 支持多种不同的数据类型 <br>
 * 1.byteBuffer <br>
 * 2.charBuffer <br>
 * 3.shortBuffer<br>
 * 4.IntBuffer<br>
 * 5.LongBuffer<br>
 * 6.FloatBuffer <br>
 * 7.DubooBuffer <br>
 * 上述缓冲区管理的方式 几乎<br>
 * 通过allocate() 获取缓冲区 <br>
 * 二、缓冲区核心的方法 put 存入数据到缓冲区 get <br> 获取缓冲区数据 flip 开启读模式
 * 三、缓冲区四个核心属性<br>
 * capacity:缓冲区最大容量,一旦声明不能改变。 limit:界面(缓冲区可以操作的数据大小) limit后面的数据不能读写。
 * position:缓冲区正在操作的位置
 */
public class test001 {
    public static void main(String[] args) {
        //1.指定缓冲区的大小1024
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        System.out.println("-------------------");
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());
        // 2.向缓冲区存放5个数据
        byteBuffer.put("abcd1".getBytes());
        System.out.println("--------------------");
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());
        // 3.开启读模式
        byteBuffer.flip();
        System.out.println("----------开启读模式...----------");
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());
        byte[] bytes = new byte[byteBuffer.limit()];
        byteBuffer.get(bytes);
        System.out.println(new String(bytes, 0, bytes.length));
        System.out.println("----------重复读模式...----------");
        byteBuffer.rewind();
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());
        byte[] bytes2 = new byte[byteBuffer.limit()];
        byteBuffer.get(bytes2);
        System.out.println(new String(bytes2, 0, bytes2.length));
        // 5.clean 清空缓冲区  数据依然存在,只不过数据被遗忘
        System.out.println("----------清空缓冲区...----------");
        byteBuffer.clear();
        System.out.println(byteBuffer.position());
        System.out.println(byteBuffer.limit());
        System.out.println(byteBuffer.capacity());
        System.out.println((char)byteBuffer.get());
    }
}

4.结果

-------------------
0
1024
1024
--------------------
5
1024
1024
----------开启读模式...----------
0
5
1024
abcd1
----------重复读模式...----------
0
5
1024
abcd1
----------清空缓冲区...----------
0
1024
1024
a

5.分析

5.1.这一步其实是当我们刚开始初始化这个buffer数组的时候,开始默认是这样的

 5.2.但是当你往buffer数组中开始写入的时候几个字节的时候就会变成下面的图,position会移动你数据的结束的下一个位置.

5.3.这个时候你需要把buffer中的数据写到channel管道中,所以此时我们就需要用这个byteBuffer.flip()方法,当你调用完这个方法时,这个时候就会变成下面的图了,这样的话其实就可以知道你刚刚写到buffer中的数据是在position---->limit之间(重复读结果是一样的)。

5.4.这时底层操作系统就可以从缓冲区中正确读取这 5 个字节数据发送出去了。在下一次写数据之前我们在调一下 clear() 方法。缓冲区的索引状态又回到初始位置。

四、make与rest的用法

1.标记(mark)与重置(reset):标记是一个索引,通过Buffer中的mark()方法指定Buffer中一个特定的position,之后可以通过调用reset()方法恢复到这个position。

2.代码

public class Test002 {
    public static void main(String[] args) {
        ByteBuffer buf = ByteBuffer.allocate(1024);
        String str = "abcd1";
        buf.put(str.getBytes());
        // 开启读取模式
        buf.flip();
        byte[] dst = new byte[buf.limit()];
        buf.get(dst, 0, 2);
        buf.mark();
        System.out.println(new String(dst, 0, 2));
        System.out.println(buf.position());
        System.out.println("---------------------------");
        buf.get(dst, 2, 2);
        System.out.println(new String(dst, 2, 2));
        System.out.println(buf.position());
        buf.reset();
        System.out.println("重置恢复到mark位置..");
        System.out.println(buf.position());
    }
}

3.结果

ab
2
---------------------------
cd
4
重置恢复到mark位置..
2

五、结束

1.下篇继续讲解java基础之nio编程的直接缓冲区与非直接缓冲区的区别以及安全性。Always keep the faith!!!

发布了122 篇原创文章 · 获赞 64 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/chenmingxu438521/article/details/103967066
今日推荐