使用Java的NIO如何快速读取文件之10G让你秒读完

举报
DRS技术快客 发表于 2020/11/30 20:36:37 2020/11/30
【摘要】 概述Java NIO(New IO) 是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同, NIO支持面向缓冲区的、基于通道的IO操作。 NIO将以更加高效的方式进行文件的读写操作。NIO关键特性Buffer在NIO中与Channel交互的是Buffer,Buffer可以理解成内存中的一块...

概述

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
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。