好记性不如烂笔头,特将今天研究的内容记录到我的仓库
- FileChannel 应用
对于读写文件,可能会使用到FileOutputStream、FileOutputStream , RandomAccessFile等类,他们都有一个getChannel()方法
例如:
// throws IOException
FileChannel channel = new FileOutputStream("data.txt").getChannel();
channel = new FileInputStream("data.txt").getChannel();
channel = new RandomAccessFile(new File("data.txt"),"rw").getChannel();
通过该方法可以获得一个FileChannel类。
在FileChannel类中主要有这几个方法, write(), read()
例如:
// 写入
channel.write(ByteBuffer.wrap("use RandomAccessFile to write something.".getBytes()));
// 创建缓冲区大小
ByteBuffer buf = ByteBuffer.allocate(1024);
buf = ByteBuffer.allocateDirect(100);
channel.read(buf);
- ByteBuffer
ByteBuffer的 allocate 和 allocateDirect区别在于
- 前者是将byte数组包装到非直接字节缓冲区(堆缓冲区)
- 而后者却是在直接字节缓冲区,操作的数据直接在内核空间,对于内存的分配和释放所需要的时间都要高于非直接字节缓冲区,但是运行效率高于非直接字节缓冲区。
- 因此,数据量较小的情况下使用allocate较好,反之使用allocateDirect
最后对于 buf.flip ,顾名思义,反转缓冲区。
从源码案例部分可以看到 , buf 保存了一个数据magic,然后输入流读取该管道,通过buf.flip反转缓冲区,最后out输出流将buf内容写出。
细看
ByteBuffer 继承Buffer
在Buffer的flip方法中,我们可以看到,它的底层实现是由limit,position,mark三个部分组成。
因为java没有指针的概念,因此这三个或许就是Buffer的实现核心。
可以再看看其它方法
等等,这里不列举了,最后总结以下内容:
position 表示当前有效数据的指针位置,limit表示数据有效的范围上限,mark是position指针的标记作用,capacity是整个buffer的大小。
它们的关系可以表示为: mark<=position<=limit<=capacity