一.用缓冲器操纵数据
Buffer由数据和可以高效的访问及操纵这些数据的四个索引组成,这四个索引是:mark
(标记),position
(位置),limit
(界限),和capacity
(容量)。
-
mark
(标记):用于重复一个读入和写出操作 -
position
(位置):下一个值的读写位置 -
limit
(界限):含有意义数据读写的范围 -
capacity
(容量):可以储存在缓冲区中的最大数据容量
这些值满足以下条件:
0<= mark <= position <= limit <= capacity
下图时用于查询、设置和复位他们的值得方法:
二.操作示例
//交换相邻字符
import java.nio.*;
import com.bruceeckel.simpletest.*;
public class UsingBuffers {
private static Test monitor = new Test();
private static void symmetricScramble(CharBuffer buffer){
while(buffer.hasRemaining()) {
buffer.mark();
char c1 = buffer.get();
char c2 = buffer.get();
buffer.reset();
buffer.put(c2).put(c1);
}
}
public static void main(String[] args) {
char[] data = "UsingBuffers".toCharArray();
ByteBuffer bb = ByteBuffer.allocate(data.length * 2);
CharBuffer cb = bb.asCharBuffer();
cb.put(data);
System.out.println(cb.rewind());
symmetricScramble(cb);
System.out.println(cb.rewind());
symmetricScramble(cb);
System.out.println(cb.rewind());
}
}
上述代码会输出如下信息:
UsingBuffers
sUniBgfuefsr
UsingBuffers
刚进入缓冲器时的状态如下:
当操纵到while循环时,使用mark()调用来设置mark的值,此时,缓冲器状态如下:
两个get调用把前两个字符保存到c1和c2中,调用玩这两个方法后,缓冲器如下:
使用reset方法可以把position的位置设为mark的值:
两个put()方法先写c2,接着写c1:
在下一次循环迭代期间,将mark设置为position的值:
这个过程持续到遍历完整个缓冲器。while循环的最后,position只想缓冲期的末尾。由于打印缓冲器只能打印从position到limit之间的字符,因此需要使用rewind()吧position设置到缓冲器的开始位置:
三.内存映射文件
- 内存映射文件允许我们创建和修改那些因为太大而不能放入内存的文件。 有了内存映射文 件,我们就可以假定整个文件都放在内存中,而且可以完全把它当作非常大的数组来访问。 这种方法极大地简化了用于修改文件的代码。
- MappedByteBuffer是一种特殊类型的直接缓冲器,继承自ByteBuffer。需要指定映射文件的初始位置和映射区域的长度,可以只对文件中的部分进行映射。
3.映射文件中的所有输出必须使用RandomAccessFile。
四.文件加锁
文件加锁有以下两种方式:
tryLock()
:非阻塞式,它会尝试获取锁,无法获取是直接返回调用方法
lock()
:阻塞式,他将阻塞进程直至获取锁
使用方法如下:
FileOutputStream fos = new FileOutputStream("test.txt");
//加锁
FileLock f = fos.getChannel().tryLock();
//释放锁
f.release();
可对文件部分加锁
tryLock(long position, long size , boolean shared);
lock(long position, long size , boolean shared);
position指定加锁位置,size制定加锁大小,shared指定是否是共享锁。对独占锁和共享锁的支持必须由底层系统提供,系统不支持共享锁时,它会使用独占锁。锁的类型可以通过FileLockShared()进行查询。