2025年java buffer nio_JAVA NIO系列(三) Buffer 解读

java buffer nio_JAVA NIO系列(三) Buffer 解读缓冲区分类 NIO 中的 buffer 用于和通道交互 数据是从通道读入缓冲区 从缓冲区中写入通道的 Buffer 就像一个数组 可以保存多个类型相同的数据 每种基本数据类型都有对应的 Buffer 类 缓冲区的属性 1 capacity 容量 buffer 本质是一个数组

大家好,我是讯享网,很高兴认识大家。

缓冲区分类

NIO中的buffer用于和通道交互,数据是从通道读入缓冲区,从缓冲区中写入通道的。Buffer就像一个数组,可以保存多个类型相同的数据。每种基本数据类型都有对应的Buffer类:

c761fb72edf492b7b1ce76086e4898ed.png
讯享网

缓冲区的属性

1、capacity(容量):buffer本质是一个数组,在初始化时有固定的大小,这个值就是容量。容量不可改变,一旦缓冲区满了,需要将其清空才能将继续进行读写操作。

2、position(位置):表示当前的位置,初始化时为0,当一个基本数据类型的数据写入buffer时,position会向前移动到下一个可插入数据的Buffer单元。position最大值可以是                              capacity-1。

3、limit(限制):在缓冲区写模式下,limit表示你最多能往Buffer里写多少数据,大小等于capacity;在缓冲区读模式下,limit表示能从缓冲区内读取到多少数据,因此,当切          换Buffer到读模式时,limit会被设置成写模式下的position值。

be1c6d66463ed269284b1e72b2417269.png

一、使用NIO进行文件内容的复制:

public classBufferTest

{public static void main(String[] args) throwsException

{

FileInputStream fis= new FileInputStream("d:/in.txt");

FileChannel channel=fis.getChannel();

FileOutputStream fos= new FileOutputStream("d:/out.txt");

FileChannel channel1=fos.getChannel();//初始化缓冲区

ByteBuffer buffer = ByteBuffer.allocate(20);

System.out.println("通道文件的大小:" +channel.size());

System.out.println("缓冲区初始化时当前位置:" +buffer.position());

System.out.println("缓冲区初始化时可写的限制:" +buffer.limit());

System.out.println("---------循环开始-----");//判断通道内数据是否读取完成

while(-1 !=channel.read(buffer))

{

System.out.println("缓冲区写模式下当前位置:" +buffer.position());

System.out.println("缓冲区写模式下的限制:" +buffer.limit());//将缓冲区从写模式切换到读模式

buffer.flip();

System.out.println("缓冲区读模式下当前位置:" +buffer.position());

System.out.println("缓冲区读模式下的限制:" +buffer.limit());//判断缓冲区内是否还有数据可读取

while(buffer.hasRemaining())

{

channel1.write(buffer);

}

buffer.clear();

}

channel.close();

channel1.close();

fis.close();

}

}

执行结果:

通道文件的大小:36缓冲区初始化时当前位置:0缓冲区初始化时可写的限制:20

---------循环开始-----缓冲区写模式下当前位置:20缓冲区写模式下的限制:20缓冲区读模式下当前位置:0缓冲区读模式下的限制:20缓冲区写模式下当前位置:16缓冲区写模式下的限制:20缓冲区读模式下当前位置:0缓冲区读模式下的限制:16

1、文件的大小为36个字节,缓冲区初始化的大小为20个字节,程序中进行了两次读取操作,才完成了文件内容的复制。

2、可以看到,在缓冲区写模式下,limit的大小始终等于capacity;而在读模式下,limit等于模式切换前position的大小。

二、Buffer的分配

Buffer对象的获取需要进行分配,每种类型的Buffer对象都有一个allocate方法。我们以程序中的ByteBuffer对象为例:

ByteBuffer buffer = ByteBuffer.allocate(20);

我们去跟踪下源码:

1 public static ByteBuffer allocate(intcapacity) {2 if (capacity < 0)3 throw newIllegalArgumentException();4 return newHeapByteBuffer(capacity, capacity);5 }

HeapByteBuffer(int cap, int lim) { //package-private

super(-1, 0, lim, cap, new byte[cap], 0);

//在这里已经创建一个以cap为大小的字节数组(new byte[cap])

ByteBuffer(int mark, int pos, int lim, int cap, //package-private

byte[] hb, intoffset)

{super(mark, pos, lim, cap);this.hb =hb;this.offset =offset;

}

Buffer(int mark, int pos, int lim, int cap) { //package-private

if (cap < 0)throw newIllegalArgumentException();this.capacity =cap;

limit(lim);

position(pos);if (mark >= 0) {if (mark >pos)throw newIllegalArgumentException();this.mark =mark;

}

}

//数组的创建在ByteBuffer类里面已经创建,在父类Buffer里,初始化容量、限制、位置等一些公共属性。

三、Buffer模式的切换

buffer.flip()该方法是用于将缓冲区从写模式切换到读模式,这是一种固定写法,该方法的源码如下:

public finalBuffer flip() {

limit=position;

position= 0;

mark= -1;return this;

}

调用flip()方法会将position设回0,并将limit设置成之前position的值。

四、remaind方法

public finalBuffer rewind() {

position= 0;

mark= -1;return this;

}

将position的位置设置为0,表示可以重新读取Buffer中的所有数据,limit保持不变。

五、clear方法

1 public finalBuffer clear() {2 position = 0;3 limit =capacity;4 mark = -1;5 return this;

1、一旦完成对buffer中数据的读取,需要让buffer做好再次被写入的准备,这时候可以调用clear方法来完成。

2、clear方法将position设置为0,limit设置为容量的值,也就意味着buffer被清空了,但是这个清空的概念是写入数据可以从缓冲区的指定位置开始,但buffer里面的数据并没有        删除。

3、如果buffer里面还有数据没有被读取,这个时候调用clear方法会导致那些数据被“遗忘”,因为没有标记告诉你哪些是读取过哪些没有被读取。

六、向buffer中写入数据

1、通过channel写入;

2、通过buffer的put方法写入:

buffer.put("channel".getBytes());

七、从buffer中读取数据

1、通过channel读取;

2、通过buffer的get方法读取:

byte b = buffer.get();

小讯
上一篇 2025-03-05 21:25
下一篇 2025-03-09 14:49

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/122460.html