java IO相关API探索之Buffer类
来源:互联网 发布:asio mac驱动 编辑:程序博客网 时间:2024/06/09 15:54
FileChannel类中直接通信的就是Buffer,Buffer是通道和文件之间的桥梁.大概数据交互是这样的,FileChannel可以写数据到buffer中,同时另外一个输出FileChannel也可以从buffer中读取数据。
buffer中有两种模式:读模式和写模式,读模式会从position位置开始读取到limit字节;写模式同样也会从position写到limit,但是写模式中一般limit=capacity(buffer的大小)
Buffer 中有四个变量来标示一些位置:
// Invariants: mark <= position <= limit <= capacity
private int mark = -1;
private int position = 0;
private intlimit;
private intcapacity;
这里面有一个恒不等式,就是上面指出的:mark<=position<=limit<=capacity
// Used only by direct buffers
// NOTE: hoisted here for speed in JNI GetDirectBufferAddress
longaddress;
有一个存储关于地址的变量.看解释好像是为了提高JNI的速度。下面是Buffer得构造函数,声明为default类型的,只在包里面可见
Buffer(intmark, int pos,int lim, intcap) { // package-private
if (cap < 0)
throw new IllegalArgumentException("Negative capacity: " +cap);
this.capacity =cap;
limit(lim);
position(pos);
if (mark >= 0) {
if (mark >pos)
throw new IllegalArgumentException("mark > position: ("
+mark + " > " + pos +")");
this.mark =mark;
}
}
下面是不允许重写的capacity()和position()方法:publicfinal int capacity() {
return capacity;
}
publicfinal int position() {
return position;
}
设置position的值,以便能够满足重复读取通道中已经读过的内容需求,如果设置position时,使得mark的值>position,那么mark的值将会置为-1;下面是这个方法的实现:
publicfinal Buffer position(intnewPosition) {
if ((newPosition >limit) || (newPosition < 0))
throw new IllegalArgumentException();
position = newPosition;
if (mark > position) mark = -1;
return this;
}
设置limit的值,如果limit>capacity那么抛出不合法参数异常,否则设置limit = newLimit,如果当前buffer的position的值大于limit,那么设置position=limit,要不然在写数据的时候从position读到limit会永远都写不进去了,可能会出现数据不一致或者读写数据出错的情况,这点要注意;publicfinal Buffer limit(intnewLimit) {
if ((newLimit >capacity) || (newLimit < 0))
throw new IllegalArgumentException();
limit = newLimit;
if (position >limit)position = limit;
if (mark > limit) mark = -1;
return this;
}
如果buffer调用了mark()方法,那么会使得mark的值等于position,每次读数据或者写数据的时候position会递增,设置,调用mark方法,应该可以从下次再重复读取内容了。但是在buffer中没有找到reset方法,所以目前这个作用也只是个猜测(卧槽,这不坑爹么.刚才猜测的时候全局搜索reset根本找不到.竟然在mark方法的下一个方法就是reset,这就显而易见了,position都回到了mark地方了,肯定就可以重复读取了.)
publicfinal Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}
调用clear方法会使得数据全部回归原来的状态,这样在写入buffer的时候,就又可以从position=0开始写入了,如果position = limit的话,就没有办法写入到buffer中了。
publicfinal Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
但是buffer中的内容根本不会清除,如果在clear()之后又去读里面的内容很可能就会造成问题,刚才试了试,会造成死循环:代码如下:
//读数据到buffer中,比如position=0,limit=capacity=50,输入通道中有15个字节
while(channelIn.read(buffer) != -1) {
//这样的话,buffer中的值应该是position=15,limit=capacity=50,mark=-1;调用flip()方法之后
buffer.flip();
//会使得limit= position =15,position = 0;capacity = 50,mark = -1;
channelOut.write(buffer);
//将buffer中的数据读入到输出channelOut中,这时数据为position=15,limit=capacity=50,mark=-1;
buffer.clear();
//调用buffer.clear()之后,使得limit=position = 15,position=0,capacity = limit = 50,mark = -1
channelOut.write(buffer);
//使用write的时候操作buffer,是从position到limit的数据全部读入到输出通道中。所以,buffer中的值变为:position=limit = capacity =50,那么因为position=limit所以下次再读数据进buffer得时候,因为缓冲区是满的,所以无法读数据到缓冲区,造成了读入字节数为0,这样一直循环,就会一直把数据写入到文件中,并且造成文件空洞(文件中的数据之间有空隙)。而使得数据异常(不一致)。
}
当然flip在上篇文章中就介绍过.不过好像没有说道具体实现,现在看一下具体实现,其实就是上篇说到的怎么切换到读模式的
publicfinal Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
下面这个方法,设置position=0,使得数据能够重写写入并且覆盖原来的写入,也可以使得读取的时候从头开始重复读取。
publicfinal Buffer rewind() {
position = 0;
mark = -1;
return this;
}
下面这个函数有两层含义:一个是当读取的时候,表示还有多少字节没有读过;写模式的时候表示还剩余多少空间可写。
publicfinal int remaining() {
return limit -position;
}
获取buffer的可读属性,判断是否为只读
publicabstract boolean isReadOnly();
设置当前位置之后的多少位:功能跟position(int n)一样
finalint nextGetIndex() { // package-private
if (position >=limit)
throw new BufferUnderflowException();
return position++;
}
finalint nextGetIndex(intnb) { // package-private
if (limit -position < nb)
throw new BufferUnderflowException();
int p = position;
position += nb;
return p;
}
下面这两个函数跟上面的完全一样,就是逻辑上一个是读一个是写finalint nextPutIndex() { // package-private
if (position >=limit)
throw new BufferOverflowException();
return position++;
}
final int nextPutIndex(intnb) { // package-private
if (limit -position < nb)
throw new BufferOverflowException();
int p = position;
position += nb;
return p;
}
检测从i开始的第nb个位置的数据是否合法finalint checkIndex(inti,int nb) { // package-private
if ((i < 0) || (nb >limit -i))
throw new IndexOutOfBoundsException();
return i;
}
截断缓冲区,并且调用这个方法后,这个缓冲区就会变的不可用
finalvoid truncate() { // package-private
mark = -1;
position = 0;
limit = 0;
capacity = 0;
}
总得来说,buffer的这些方法都是围绕了buffer得对象模型展开的,主要操作元素就是对象中的mark,position,limit以及capacity属性。理解了这层含义,那么对于buffer的操作便会顺心应手。- java IO相关API探索之Buffer类
- java IO相关API探索之ByteBuffer
- java IO相关API探索之FileInputStream类
- java IO相关API探索之FileChannel类
- java IO相关API探索之 AutoCloseable接口
- java IO相关API探索之Closeable和InputStream接口
- Java之IO、NIO、Buffer
- 关于golang中IO相关的Buffer类浅析
- java学习笔记(三十七)java新IO之Buffer
- Java IO系统——NIO之Buffer、Channel和Charset类
- IO之内核buffer----"buffer cache"
- IO之内核buffer----"buffer cache"
- IO之内核buffer----"buffer cache"
- [C]IO相关API
- JAVA之IO技术相关Properties类的使用
- JAVA之IO技术相关Properties类 存储配置文件信息
- java.io.File源码探索
- java nio 学习之 Buffer 类
- android选择图片或拍照图片上传到服务器(包括上传参数)
- C# System.Drawing.Region类的方法使用图解
- 关于mknod延伸到的知识点
- 1095 A+B for Input-Output Practice (VII)
- Timer和ScheduledExecutorService
- java IO相关API探索之Buffer类
- 始动:hello world-cpp
- HMM简介
- 大端模式和小端模式的概念以及使用程序来辨别
- codeforces493 A. Vasya and Football B. Vasya and Wrestling C. Vasya and Basketball
- hihoCoder:1039字符串消除
- 1096 A+B for Input-Output Practice (VIII)
- android源码在windows平台下的下载的几种方式
- 做PPT需要注意的问题