基本概念
所谓缓冲区buffer,就是“临时存贮区”的意思,是暂时存放输入输出数据的一段内存。
要使用缓冲区,肯定要先分配内存,如下:
byte[] buf = new byte[10];
这里牵涉到一个概念: 容量capacity,缓冲区的大小,分配的内存的大小,
即上面的数字10。这个大小是不可变的。为什么说不可变呢?因为,内存都分配好了,
哪还能变,如果要改变大小,就要重新分配内存,重新分配内存的话,就是新的缓冲区了,
就不是本来的那个了。:)
内存分配好了,再看怎么用。
既然是临时存储,那么缓冲区的使用过程就应该是:放入数据,然后取出数据,
由此可得,缓冲区的基本操作是put和get。
比如要往里面放数据,就put!
但放到哪里呢?
这个时候,就需要一个概念:位置position,即当前的操作位置。
比如这样:
buf[0] = (byte)2;(这里的赋值操作相当于put)
这就表示把数据2放到了0这个位置,这里的position即为0。
如果没有这个position,就只能随处乱put了。就像“禁止随处大小便”一样,
随处乱put也是不行的。随处大小便出来的东西你是不会再要的,这尚且不行,
何况put的数据后面你还要再找回来,那当然就更不能乱来了。至于取数据get,
当然完全类似,哪儿put的哪儿get就是了。
再看还需要什么属性和操作。
有个计算题,说:一辆公交车,车上有22人,到站停车,上来10个,下去15;又停一次,
上来8,下去10个;又停一次,上来18,下去20;又停一次,上来66,下去1个。
请问,公交车停了几次?相信这个笑话大家听说过了。
和这个笑话类似,往缓冲区里放数据:
put一次,再put一次,再put一次,…put了好多次之后,请问,总共put了多少次?
实际上,和公交车问题的情形相反,问put多少次,意义应该不是很大。更有意义的问题是,
put了多少数据进去?这些数据都put到哪里去了?
那put了多少数据呢?没有记录的话,还是不知道。所以,
还是要记录下来,就用dataLength来记录吧。至于put到了哪里,那肯定是从buf开始的地方开始的。
那么现在总结一下缓冲区中的概念:
1. 缓冲区的容量capacity;
2. 缓冲区存取操作put/get;
3. 操作的位置position;
4. 已存入的数据的多少dataLength。
至此,缓冲区的基本概念算是基本介绍完了。
下面介绍一下java.nio.Buffer类对buf的实现。
java.nio.Buffer类对buf的实现
Buffer类里面,属性字段有:
capacity (容量):缓冲区的容量是其空位的数量。缓冲区的容量永远不会为负并且从不会更改。
position (位置):缓冲区的位置是下一个要读取或写入的元素的索引。
缓冲区的位置永远不会为负,并且永远不会大于其限制。
limit (限制):缓冲区的限制是不应读取或写入的第一个元素的索引。
缓冲区的限制永远不会为负,并且永远不会大于其容量。
mark (标记):缓冲区的标记是在调用reset 方法时其位置将被重置到该mark位置。
如果定义的标记后,位置(position)或限制(limit)调整为小于标记的值时,
该标记将被丢弃。如果未定义标记,则调用 reset 方法将导致抛出InvalidMarkException。
这几者之间的关系式如下:
0 <= 标记 <= 位置 <= 限制 <= 容量
对比基本概念和java中Buffer的实现可以看出:
capacity的意义是相同的;
position的意义是相同的;
不同的是dataLength和limit,至于mark,感觉不到什么用,不讲了。
看limit的定义,limit是一个位置索引,表示可操作和不可操作区域的分界,
position和limit之间的距离指示了可读取/存入的字节数。
在这里,java.nio.Buffer引入了新的概念:区域的概念,可操作区域和不可操作区域。
可操作区域:在put的时候,表示还有多少空间可写入,在get的时候,表示还有多少数据可读取。
注意:可操作区域,在put和get的时候,表示的含义是不同的,一个表示可用空位的多少,
一个表示可用数据的多少。在put之后,要有一个转换的过程,之后才能从缓冲区中get数据。
boolean hasRemaining()
int remaining()
这两个方法就是用来获得可读取/存入的字节数,即可操作区域的大小。
不可操作区域:不可操作区域就是字面上的意思,即不可操作的区域。在put时,
整个buf都可以写入,因此,不可操作区域是空的;在get的时候,不可操作区域是没有数据的区域。
limit:就是上述的可操作区域和不可操作区域的分界线。
上面解释了limit的基本概念,现在再详细地看一下limit和其他几个属性间的关系:
在put写入的时候,可用空间表示还没数据的部分,则limit固定的为capacity,
capacity-limit表示为不可用的空间,limit-position表示可用空间;
在get读取的时候,可用空间表示缓冲区已有数据的部分,前半部分limit-position表示可用数据,
后半部分capacity-limit表示不能操作,因为那里没有数据;
在put和get操作之间,因为可用空间上有无数据的含义不相同,需要有一个flip操作,
来更新limit,进而更新可用空间的的含义,更新之后才能操作数据。
再看基本概念中的dataLength和java.nio.Buffer中limit概念的区别:
Buffer类中引入了新的概念:区域的概念,可操作区域和不可操作区域,
limit表示这两个区域的分界线,很直观。在区域里,limit配合position就可以得到要用到的数据。
dataLength是一个数字,只表示缓冲区中数据的多少,很不形象啊。
对比dataLength和limit,limit更加形象,直接把缓冲区分成两个部分,
每个部分的含义都很清楚。limit不爽的地方是,在写读转换的时候,要flip一下,
且只能flip一下,flip多了还会出问题。
再看mark,感觉这个好像没什么用处,跟个记录position的临时变量一样,
不知道java为什么非要这个操作不可。
方法
操作分两种:
相对操作 :操作读取或写入从当前位置开始的一个或多个元素,然后将该位置增加传输的元素的数量。
绝对操作 :操作采用显式元素索引,不会影响位置。
缓冲区基本概念中,使用的是绝对操作,这里的相对操作,只是增加使用的便利而已。
基本概念解释清楚,操作方法应该就很好理解了,就不详细解释了,写得太累了,
操作方法请参照
http://www.blogjava.net/killme2008/archive/2008/02/22/181357.html
分享到:
相关推荐
Buffer(缓冲区) - **Buffer 基础**:介绍了 Buffer 的基本概念,包括如何创建 Buffer、复制 Buffer 以及 ByteBuffer 的具体用法。 - **创建 Buffer**:讨论了多种创建 Buffer 的方法。 - **复制 Buffer**:探讨...
Java.nio引入了通道(Channel)和缓冲区(Buffer)的概念。通道代表I/O操作的来源或目的地,如文件、套接字等;缓冲区则用于临时存储数据,提供了一种更有效的方式进行数据传输。NIO的核心组件还包括选择器...
NIO的核心特性包括基于缓冲区的I/O操作和非阻塞I/O,这使得应用程序能够处理更多的连接,同时减少资源的消耗。 NIO API主要分布在以下几个包中: 1. `java.nio`:这个包定义了Buffer及其子类,例如ByteBuffer,...
- **缓冲区(Buffer)**:缓冲区是Java NIO中数据读写的基础单元。根据数据类型的不同,Java NIO 提供了多种缓冲区: - **ByteBuffer**:用于基本字节数据的缓冲。 - **CharBuffer**:用于字符数据的缓冲。 - **...
定义新的强制功能缓冲区,字节缓冲区,字符缓冲区,双缓冲区,浮点缓冲区,整数缓冲区,长缓冲区,短缓冲区,通道,可读通道和可写通道。 这些功能已为您期望的许多类实现。 还定义了函数mmap来对文件进行内存映射...
2. **缓冲区(Buffers)**:缓冲区是Java NIO的核心,它是内存块的抽象,用于在通道和应用程序之间传输数据。各种类型的原始数据类型(如byte、char、int等)都有对应的Buffer类。 3. **选择器(Selectors)**:...
NIO的核心组件包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。在给定的压缩包文件中,我们关注的是"FastCopyFile.java"、"UseFloatBuffer.java"以及NIO中的文件锁功能。 首先,让我们详细了解一下`...
NIO的主要特点是面向缓冲区,非阻塞I/O,以及选择器,这些特性使得NIO在处理大量并发连接时表现出更高的效率。在本篇文章中,我们将深入探讨Java NIO如何读取文件。 一、NIO的基本概念 1. 缓冲区(Buffer):NIO的...
总的来说,Java NIO不仅提供了非阻塞I/O的能力,还引入了新的设计概念,如通道、缓冲区和选择器,这些都极大地提高了Java在处理I/O操作时的性能和并发能力。对于需要处理大量并发连接,或者需要高效读写大文件的场景...
传统的Java I/O基于字节流和字符流,而NIO则提供了通道(Channels)和缓冲区(Buffers)的概念,以及非阻塞I/O操作的能力。本资料"java-nio.rar"主要探讨的是如何使用Java NIO实现异步连接池,这在高并发场景下尤其...
缓冲区类型包括ByteBuffer、CharBuffer、IntBuffer、DoubleBuffer等,它们都继承自`java.nio.Buffer`。 3. **选择器(Selector)**:用于监听多个通道的事件(如连接就绪、数据到达等),当某个通道准备好进行读写...
而Java NIO引入了Channel(通道)和Buffer(缓冲区)的概念,以及Selector(选择器)机制,使得一个线程可以同时监控多个通道的事件,大大提高了处理效率。以下是NIO的主要组件和特性: 1. **Channel**:类似于流,...
01-Java NIO-课程简介....17-Java NIO-Buffer-缓冲区分片.mp4 18-Java NIO-Buffer-只读缓冲区.mp4 19-Java NIO-Buffer-直接缓冲区.mp4 21-Java NIO-Selector-概述.mp4 23-Java NIO-Selector-示例代码(客户端).mp4 24
NIO的核心在于通道(Channel)和缓冲区(Buffer)的概念。在BIO中,数据读写都通过流进行,而NIO则允许数据在通道和缓冲区之间直接传输,这减少了数据复制的开销。 1. **通道(Channel)**:通道类似于流,但它们可以...
Java NIO提供了多种类型的缓冲区,如ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer和LongBuffer等,它们都继承自抽象类Buffer。缓冲区具有容量、限制和位置等属性,以及诸如put、get和flip等操作...
NIO的关键组件包括通道(Channels)、缓冲区(Buffers)和选择器(Selectors)。 【Java NIO的非阻塞I/O】 非阻塞I/O模型是NIO的核心优势,它基于操作系统提供的多路复用I/O机制,如Unix的`select`或Windows的`...
NIO在处理大量并发连接时表现出色,因为它基于通道(Channels)和缓冲区(Buffers)进行数据传输,而非传统的流(Streams)模型。在本主题中,我们将探讨如何利用Java NIO和charset来自动识别字符集。 首先,让我们...
本文主要关注的是Java NIO中的ByteBuffer,一个关键的数据容器,用于在通道(Channel)和缓冲区(Buffer)之间传输数据。ByteBuffer的用法是Java NIO学习中的核心内容。 首先,我们了解下ByteBuffer的基本概念。...