使用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)