1.简介
Buffer是一种用于特定的基本类型数据的容器,是特定的基本类型元素的线性、有限序列。
1.1 Buffer有四个相当重要的属性:
1)capacity:容量,Buffer所能够容纳的基本类型数据的数量。
2)mark:标记,Buffer中的一个位置
3)position:位置,下一个读写操作的元素在Buffer中的位置。
4)limit:限制,禁止读写操作的第一个元素的索引
1.2 四个属性之间的关系
0 <= 标记 <= 位置 <= 限制 <= 容量
1.3 影响四个属性的相关操作
1)public final Buffer mark()
在Buffer的位置设置标记
2)public final Buffer reset()
将Buffer的位置设置为之前的标记值,如果标志不存在则抛出InvalidMarkException
3)public final Buffer position(int newPosition)
设置Buffer的位置,如果标记已定义并且大于新的位置,则要丢弃该标记
newPosition范围[0,limit],否则抛出IllegalArgumentException
4)public final Buffer limit(int newLimit)
设置此缓冲区的限制。
如果位置大于新的限制,则它被设置为此新限制。
如果标记已定义并且大于新限制,则要丢弃该标记。
newPosition范围[0,capacity],否则抛出IllegalArgumentException
5)public final Buffer flip()
反转此缓冲区。
首先对当前位置设置限制,然后将该位置设置为零。
如果已定义了标记,则丢弃该标记。
效果等同于Buffer.limit(Buffer.position()); + Buffer.position(0);
6)public final Buffer rewind()
重绕此缓冲区。将位置设置为零并丢弃标记。
效果等同于Buffer.position(0);
7)public final Buffer clear()
清除此缓冲区。将位置设置为零,限制设置为该容量,并且丢弃标记。
注:此方法不能实际擦除缓冲区中的数据
效果等同于Buffer.limit(Buffer.capacity()); + Buffer.position(0);
8)put/get等当前位置存取方法均会使位置向前移动N个单位,存取操作的位置不能大于限制
9)put/get等绝对位置存取方法均不会改变Buffer的位置和限制
2.个人总结
1)关于写
Buffer通过position来控制读写操作的元素位置,每次写操作后都会将position向后移动写入数据的长度,因此一个连续的写操作的作用范围为从第1个写操作的position1到第N个写操作的positionN,即[position1, positionN+length(dataN))且0<=position1<positionN+length(dataN)<=limit。
2)关于读
由写的过程可知写的内容位于[position1, positionN+length(dataN))之间,所以读取写内容的时候也必须读取该范围的内容。
3)程序使用
程序使用Buffer时通过每次记录写操作的position1和positionN+length(dataN)不可行,因为可能对象A对Buffer进行写操作,并且只返回Buffer对象给需要读Buffer的对象B。
所以要利用Buffer的属性进行读写操作,使得
每次写操作开始前使postion=0,limit=capacity,这样写操作范围为[0, limit) = [0, capacity),即调用方法clear()
在写操作结束后读取内容前使limit=position,postion=0,这样读操作范围为[0, limit) = [position1, positionN+length(dataN)),即调用方法flip()
第一次读取内容后要重复读取内容前只需使postion=0,这样读操作范围为[0, limit) = [position1, positionN+length(dataN)),即调用方法rewind()
3.实例
package com.siyuan.test.jdk.nio; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.InvalidMarkException; public class BufferTest { /** * @param args */ public static void main(String[] args) { int BSIZE = 1024; ByteBuffer bBuffer = ByteBuffer.allocate(BSIZE); System.out.println("初始化..."); System.out.println(getBufferStatus(bBuffer)); bBuffer.putChar('a'); System.out.println("在位置写入字符a后"); System.out.println(getBufferStatus(bBuffer)); bBuffer.mark(); bBuffer.putChar('b'); System.out.println("在位置设置标记,写入字符b后"); System.out.println(getBufferStatus(bBuffer)); int lastPosition = bBuffer.position(); //记录缓冲区有效字符的终结位置 bBuffer.reset(); //效果等同于bBuffer.position(2); System.out.println("将位置设置为标志后"); System.out.println(getBufferStatus(bBuffer)); //读数据 //设置位置,如果标记已定义并且大于新的位置,则要丢弃该标记 bBuffer.position(lastPosition); /* *将限制设置为位置,然后将位置设置为0,如果已定义了标记,则丢弃该标记 *常用于向buffer中写入数据后和从buffer中读取数据前 *效果等同于 *bBuffer.limit(bBuffer.position()); *bBuffer.position(0); */ bBuffer.flip(); System.out.println("还原位置,flip后"); System.out.println(getBufferStatus(bBuffer)); while (bBuffer.hasRemaining()) { System.out.print(bBuffer.getChar()); } System.out.println("读取完位置和限制之间的数据后"); System.out.println(getBufferStatus(bBuffer)); //重新读取 /* * 重绕此缓冲区。将位置设置为零并丢弃标记。 * 效果等同于 * Buffer.position(0); */ bBuffer.rewind(); System.out.println("rewind后"); System.out.println(getBufferStatus(bBuffer)); while (bBuffer.hasRemaining()) { System.out.print(bBuffer.getChar()); } System.out.println("读取完位置和限制之间的数据后"); System.out.println(getBufferStatus(bBuffer)); //重新写入数据 /* * 清除此缓冲区。将位置设置为零,限制设置为该容量,并且丢弃标记。 * 注:此方法不能实际擦除缓冲区中的数据 * 通过position和limit来确定有效数据的存储区域 * 效果等同于 * bBuffer.limit(buffer.capacity()); * bBuffer.position(0); */ bBuffer.clear(); System.out.println("clear后"); System.out.println(getBufferStatus(bBuffer)); bBuffer.putChar('b'); bBuffer.putChar('b'); bBuffer.putChar('c'); bBuffer.putChar('c'); System.out.println("在位置写入bbcc后"); System.out.println(getBufferStatus(bBuffer)); /* * 绝对位置读取,不影响Buffer的属性 */ System.out.println(bBuffer.getChar(4)); System.out.println("在绝对位置4读取字符后"); System.out.println(getBufferStatus(bBuffer)); /* * 绝对位置写入,不影响Buffer的属性, * 且写入方式为覆盖,而不是插入 */ bBuffer.putChar(4, 'd'); System.out.println("在绝对位置4写入字符d后"); System.out.println(getBufferStatus(bBuffer)); System.out.println("重新读取Buffer的内容"); bBuffer.flip(); while (bBuffer.hasRemaining()) { System.out.print(bBuffer.getChar()); } } public static final String getBufferStatus(Buffer buffer) { StringBuilder str = new StringBuilder(); str.append("容量:").append(buffer.capacity()) .append(",位置:").append(buffer.position()) .append(",限制:").append(buffer.limit()); boolean markExist = false; try { int position = buffer.position(); buffer.reset(); markExist = true; buffer.position(position); } catch(InvalidMarkException e) { } str.append(",存在标志: ").append(markExist); return str.toString(); } }
运行结果:
初始化... 容量:1024,位置:0,限制:1024,存在标志: false 在位置写入字符a后 容量:1024,位置:2,限制:1024,存在标志: false 在位置设置标记,写入字符b后 容量:1024,位置:4,限制:1024,存在标志: true 将位置设置为标志后 容量:1024,位置:2,限制:1024,存在标志: true 还原位置,flip后 容量:1024,位置:0,限制:4,存在标志: false ab读取完位置和限制之间的数据后 容量:1024,位置:4,限制:4,存在标志: false rewind后 容量:1024,位置:0,限制:4,存在标志: false ab读取完位置和限制之间的数据后 容量:1024,位置:4,限制:4,存在标志: false clear后 容量:1024,位置:0,限制:1024,存在标志: false 在位置写入bbcc后 容量:1024,位置:8,限制:1024,存在标志: false c 在绝对位置4读取字符后 容量:1024,位置:8,限制:1024,存在标志: false 在绝对位置4写入字符d后 容量:1024,位置:8,限制:1024,存在标志: false 重新读取Buffer的内容 bbdc
4.参考资料
JDK文档
相关推荐
可以动态演示nio中buffer的相关操作,直观看到各种重要数据的变化,方便大家更好的理解nio的buffer模型
05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 08-Java NIO-Channel-ServerSocketChannel.mp4 09-Java NIO-Channel-SocketChannel.mp4 10-Java NIO-Channel-...
主要介绍一些关于NIO 的基础知识,有浅到深
05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 07-Java NIO-Channel-Socket通道-概述.mp4 08-Java NIO-Channel-ServerSocketChannel.mp4 09-Java NIO-Channel-...
尚硅谷_NIO_缓冲区(Buffer)的数据存取 ·03. 尚硅谷_NIO_直接缓冲区与非直接缓冲区 ·04. 尚硅谷_NIO_通道(Channel)的原理与获取 ·05. 尚硅谷_NIO_通道的数据传输与内存映射文件 ·06. 尚硅谷_NIO_分散读取与聚集...
主要介绍了JAVA NIO之Buffer(缓冲区)的相关资料,文中讲解非常细致,帮助大家更好的学习JAVA NIO,感兴趣的朋友可以了解下
主要介绍了Java NIO Buffer过程详解,缓冲区在java nio中负责数据的存储。缓冲区就是数组。用于存储不同数据类型的数据。,需要的朋友可以参考下
Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...
java NIO是 java New IO 的简称,在 jdk1.4 里提供的新 api 。 Sun 官方标榜的特性如下: – 为所有的原始类型提供 (Buffer) 缓存支持。 – 字符集编码解码解决方案。 – Channel :一个新的原始 I/O 抽象。 – 支持...
Java NIO系列教程 Java NIO Channel Buffer Selector SocketChannel
NIO即non-blocking IO,顾名思义是一种非阻塞模型。NIO的目的就是实现一个线程处理多个连接。实现多人聊天消息转发,用户发送消息同步到服务中的其他客户端,运用到了nio中buffer、socket、selector。 1、Channel,...
Next, you'll learn about NIO's buffer, channel, selector, regular expression, charset, and formatter APIs. Finally, you'll discover NIO.2's offerings in terms of an improved file system interface, ...
Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...
NIO是NewI/O的简称,具有以下特性:为所有的原始类型提供(Buffer)缓存支持;使用java.nio.charset.Charset作为字符集编码解码解决方案;增加通道(channel)对象,作为新的原始I/O抽象;支持锁和内存映射文件的...
ReadWriter} nio的Copy方法同时从io.Reader复制到提供的nio.Buffer,然后从nio.Buffer复制到io.Writer。 这样,阻止写入不会降低io.Reader的速度。 import ( "github....
java nio作者倾力所写的简单易懂的NIO学习指南,让你顺利拿下NIO开发,包括了NIO中的Buffer,Channel,Selector的介绍,理论&代码都有,是你学习NIO的不二法宝~
The NIO package includes many things that have been missing from previous editions of Java that are critical to writing high-performance, large-scale applications: improvements in the areas of buffer ...
2.2 NIO概述 NIO NIO ==> New IO(新IO), Non-Block IO(非阻塞IO) NIO非阻塞IO,运行当前程序在处理IO事务时,不会影响其他程序的运行,可以在不使用多线程的情况下,满足IO操作要求。...java.nio.Buffer Buffe
NULL 博文链接:https://wutaoo.iteye.com/blog/419232