使用Java的NIO如何快速读取文件之10G让你秒读完
概述
Java NIO(New IO) 是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同, NIO支持面向缓冲区的、基于通道的IO操作。 NIO将以更加高效的方式进行文件的读写操作。
NIO关键特性Buffer
在NIO中与Channel交互的是Buffer,Buffer可以理解成内存中的一块区域,而NIO Buffer就是对这块内存的封装。
NIO几种Buffer的比较
- DirectByteBuffer
分配的内存区域在内存中,通过allocateDirect创建,底层通过Unsafe的allocateMemory方法进行内存分配,它的释放机制由JDK提供的钩子方法,当buffer对象被GC回收的时候会执行这个钩子方法进行内存释放。 - HeapByteBuffer
分配的内存区域位于jvm中,意味着数据的多一次copy,但是回收过程可由GC保证。 - MappedByteBuffer
通过将文件中的一个区域直接映射到内存中来创建,这样效率确实很高,但是意味着一个问题,它的内存占用就无法确定了。对于我们10g的场景下,需要进行多次map的场景,内存占用就是直线攀升了。
以HeapByteBuffer为读取buffer进行读取
接下来我们将以大文件按行读取为需求背景进行编写代码
```
private byte[] readLine(FileChannel fileChannel, ByteBuffer byteBuffer) throws IOException {
int limit = 0;
byte[] temp = null;
int capcity = byteBuffer.capacity();
int position = byteBuffer.position();
if (byteBuffer.remaining() == 0) { // nothing to read
byteBuffer.clear(); // before read should reset position
if (-1 == fileChannel.read(byteBuffer)) {
readedPosition = -1;
return null;
}
readedPosition = byteBuffer.position();
limit = 0;
position = 0;
byteBuffer.clear(); // reset position
}
while (byteBuffer.remaining() > 0 && byteBuffer.get() != 0x0A) {
limit ++;
if (byteBuffer.position() >= readedPosition) { // this buffer read over
byteBuffer.position(position);
byteBuffer.limit(readedPosition);
temp = getBytes(byteBuffer, null);
byteBuffer.clear(); // before read should reset position
if (-1 == fileChannel.read(byteBuffer)) {
readedPosition = -1;
return temp;
}
readedPosition = byteBuffer.position();
limit = 0;
position = 0;
byteBuffer.clear(); // reset position
}
}
byteBuffer.position(position);
byteBuffer.limit(position + limit);
ByteBuffer cache = byteBuffer.slice();
limit ++;//skip \n
- 点赞
- 收藏
- 关注作者
评论(0)