java.nio  --- 定义了 Buffer 及其数据类型相关的子类。其中被 java.nio.channels 中的类用来进行 IO 操作的 ByteBuffer 的作用非常重要。

java.nio.channels----定义了一系列处理 IO 的 Channel 接口以及这些接口在文件系统和网络通讯上的实现。通过 Selector 这个类,还提供了进行非阻塞 IO 操作的办法。这个包可以说是 NIO API 的核心。

java.nio.channels.spi----定义了可用来实现 channel 和 selector API 的抽象类。

java.nio.charset----  定义了处理字符编码和解码的类。

java.nio.charset.spi---- 定义了可用来实现 charset API 的抽象类。

java.nio.channels.spi 和 java.nio.charset.spi 这两个包主要被用来对现有 NIO API 进行扩展,在实际的使用中,我们一般只和另外的 3 个包打交道。

一、java.nio

  1、初步介绍

   这个包主要定义了 Buffer 及其子类。 Buffer 定义了一个线性存放 primitive type 数据的容器接口。对于除 boolean 以外的其他 primitive type ,都有一个相应的 Buffer 子类, ByteBuffer 是其中最重要的一个子类。

A buffer is a linear, finite sequence of elements of a specific primitive type.  Aside from its content, the essential properties of a buffer are its capacity, limit, and position.

buffer是一种线性而且有限的存储区域,对于buffer来讲由三个重要的属性(其实还有一个叫做mark)

A buffer's capacityis the number of elements it contains.  The capacity of a buffer is never negative and never changes.

  表示buffer的容量大小,非负,不可改变。

A buffer's limit is the index of the first element that should not be read or written.  A buffer's limit is never negative and is never  greater than its capacity.

  表示第一个不能读取元素的下标,比如说,存了3个元素(下标0,1,2) 此时limit=3.

A buffer's  position is the index of the next element to be  read or written.  A buffer's position is never negative and is never   greater than its limit.

  表示当前可用的第一个元素。

[注] There is one subclass of this class for each non-boolean primitive type. 该类的子类型不是boolean类型。

  所有的子类中都定义了get和put方法。

A buffer's mark is the index to which its position will be reset when the reset method is invoked.  The mark is not always defined, but when it is defined it is never negative and is never greater than the position.  If the mark is defined then it is discarded when the position or the limit is adjusted to a value smaller than the mark.  If the mark is not defined then invoking the reset method causes an InvalidMarkException to be thrown.

  一个临时存放的位置下标。调用 mark() 会将 mark 设为当前的 position 的值,以后调用 reset() 会将 position 属性设置为 mark 的值。 mark 的值总是小于等于 position 的值,如果将 position 的值设的比 mark 小,当前的 mark 值会被抛弃掉。

 Clearing, flipping, and rewinding

clear : makes a buffer ready for a new sequence of   channel-read or relative put operations: It sets the limit to the  capacity and the position to zero. limit = capacity ,position = 0 ------一般在写入缓存时候使用。

flip makes a buffer ready for a new sequence of   channel-write or relative get  operations: It sets the limit to the   current position and then sets the position to zero.

  把limit设置为position,把position 设置为0。 ---- 一般在读取buffer中的数据的时候使用。

 rewind  makes a buffer ready for re-reading the data that   it already contains  It leaves the limit unchanged and sets the position to zero.  此时limit不会改变,position的值设置为0. ----实现对buffer数据的重新读入。

  此外还可以将buffer查看值否为只读的状态,isReadOnly()

 Thread safety??  

  Buffers are not safe for use by multiple concurrent threads.  If a buffer is to be used by more than one thread then access to the buffer should be controlled by appropriate synchronization.

  buffer不是线程安全的,如果多线程访问必须对其加以同步控制。

2、深入源码

  源码中对于四个访问位置的控制参数的初始设置是这样的:mark <= position <= limit <= capacity,其中mark= -1,position = 0;

  1)、构造函数

    Buffer的构造函数是包内私有的,所以没有办法在其他的包内实现通过构造函数获取实例。具体什么方法稍后会有介绍。

  2)、参数

    上面提到的四个参数,mark <= position <= limit <= capacity 其中的position和limit都有相应的方法来获取当前的值和设置新值,但是设置的时候需要保证其取值范围的有效性。

    上面提到的mark()方法:  

     public final Buffer mark() {
mark = position;
return this;
}
    public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}

  3)、读取、写入模式的切换

  clear() ----- 重新写入数据使用,将当前可用的第一个位置指向了buffer的首位值。

     public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}

  flip() ---- 用于读取buffer中的数据

    public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}

  rewind()---- 这其中,limit不变,position =0 ,指向了第一个位置处,用于重新读取。

    public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}

  4)、当前的可用空间

    hasRemaining() ---是否还有可用的空间

    remaining() ----查看还有多少可用的空间

  5)、获取实例

    由于Buffer是一个抽象类,没有提供相应的获取实例的方法,这个只能交给子类来完成了。

下面以IntBuffer为例:

     public static IntBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapIntBuffer(capacity, capacity);
}

  通过这样的方法来获取实例,HeaoIntBuffer() 这个是IntBuffer的子类。这个类真正实现了IntBuffer的时机操作。而实际在IntBuffer中就提供了一系列重载的put,get方法。

  至于get,put方法如何使用,不再赘述。

欢迎指正交流。

一天一个类--NIO 之Buffer的更多相关文章

  1. Java NIO 之 Buffer

    Java NIO 之 Buffer Java NIO (Non Blocking IO 或者 New IO)是一种非阻塞IO的实现.NIO通过Channel.Buffer.Selector几个组件的协 ...

  2. Java NIO之Buffer(缓冲区)

    ​ Java NIO中的缓存区(Buffer)用于和通道(Channel)进行交互.数据是从通道读入缓冲区,从缓冲区写入到通道中的. ​ 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这 ...

  3. JAVA NIO简介-- Buffer、Channel、Charset 、直接缓冲区、分散和聚集、文件锁

    IO  是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. Java标准io回顾 在Java1.4之前的I/O系统中,提供 ...

  4. Java基础知识强化之IO流笔记74:NIO之 Buffer

    Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...

  5. Java NIO -- 缓冲区(Buffer)的数据存取

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

  6. NIO的Buffer&Channel&Selector

    java的NIO和AIO Buffer position.limit.capacity 初始化 Buffer 填充 Buffer 提取 Buffer 中的值 mark() & reset() ...

  7. Java NIO 之 Buffer(缓冲区)

    一 Buffer(缓冲区)介绍 Java NIO Buffers用于和NIO Channel交互. 我们从Channel中读取数据到buffers里,从Buffer把数据写入到Channels. Bu ...

  8. Java NIO:Buffer、Channel 和 Selector

    Buffer 一个 Buffer 本质上是内存中的一块,我们可以将数据写入这块内存,之后从这块内存获取数据. java.nio 定义了以下几个 Buffer 的实现,这个图读者应该也在不少地方见过了吧 ...

  9. java学习-NIO(二)Buffer

    当我们需要与 NIO Channel 进行交互时, 我们就需要使用到 NIO Buffer, 即数据从 Buffer读取到 Channel 中, 并且从 Channel 中写入到 Buffer 中.缓 ...

随机推荐

  1. hdoj 3018 Ant Trip(无向图欧拉路||一笔画+并查集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3018 思路分析:题目可以看做一笔画问题,求最少画多少笔可以把所有的边画一次并且只画一次: 首先可以求出 ...

  2. 制作cdlinux u盘启动

    U盘一个 CDlinux的iso镜像文件 UltraISO grub4dos grubinst 方法/步骤1 1 [第一步]:用UltraISO把CDlinux的镜像刻录进U盘. 打开UltraISO ...

  3. Maven模块聚合与继承

    聚合 假如有account-email和account-persist两个模块,我们想要一次构建这两个项目,这时须要用到聚合. 聚合模块 package值必须为pom 必须有元素modules mod ...

  4. 【剑指offer】面试题43:n个骰子的点数

    第一种思路是,每一个骰子的点数从最小到最大,如果为1-6,那么全部的骰子从最小1開始,我们如果一种从左向右的排列,右边的最低,索引从最低開始,推断和的情况. def setTo1(dices, sta ...

  5. .c和.h文件的区别(头文件与之实现文件的的关系~ )

     .c和.h文件的区别 一个简单的问题:.c和.h文件的区别 学了几个月的C语言,反而觉得越来越不懂了.同样是子程序,可以定义在.c文件中,也可以定义在.h文件中,那这两个文件到底在用法上有什么区别呢 ...

  6. 【原】Spring和Dubbo整合案例和过程

    Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看,Dubbo采用的是一种非常简单的模 ...

  7. list, tuple, dict, set的用法总结

    d = [1, 2, 3, 4, 5, 5] #list print(d) e = ([1, 2], 3, 4, 5555, 5555)#tuple print(e) f = {'Michael':8 ...

  8. CAN总线与RS485的比较

    CAN总线与RS485的比较 http://blog.csdn.net/reille/article/details/6135546 can总线与485总线有什么区别?  http://blog.16 ...

  9. 1724: [Usaco2006 Nov]Fence Repair 切割木板( 贪心 )

    倒过来看 , 每次总是选择最短的两块木板合并 , 用heap维护 ------------------------------------------------------------------- ...

  10. poj 2094 多项式求和。

    /** 给出多项式 p(x) = an*x^n + an-1*x^(n-1)..... + a1*x + a0; 给定n,l,k,m 计算 x 从 l到 l+k-1 的p(x)的后m 位的平方的和 用 ...