ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

使用FileChannels在Java中串联哪种大型文件更有效

2019-12-08 11:12:57  阅读:305  来源: 互联网

标签:bytebuffer filechannel concatenation nio java


我想找出在串联Java中的文本文件时我想出的哪一种方法更好.如果有人可以提供一些见解,并且可以就内核级别发生的事情进行共享,这些事情可以解释这些写入FileChannel的方法之间的区别,那么我将不胜感激.

据我从文档和其他Stack Overflow对话中了解到,allocateDirect在驱动器上分配空间,并且大多数情况下避免使用RAM.我担心如果File infile很大(例如1GB),则用allocateDirect创建的ByteBuffer可能有溢出或未分配的可能.目前,在我们开发软件时,我保证文件将不大于2 GB.但将来可能会达到10GB或20GB.

我观察到transferFrom循环从未经历过一次以上循环……因此似乎可以一次成功写入整个infile;但我尚未使用大于60MB的文件进行测试.我循环了一下,因为文档指定了不能保证一次写入多少内容.使用transferFrom仅能在我的系统上接受int32作为其count参数,我一次不能指定超过2GB的内存…再次,内核专业知识将帮助我理解.

在此先感谢您的帮助!!

使用ByteBuffer:

boolean concatFiles(StringBuffer sb, File infile, File outfile) {

    FileChannel inChan = null, outChan = null;

    try {

        ByteBuffer buff = ByteBuffer.allocateDirect((int)(infile.length() + sb.length()));
        //write the stringBuffer so it goes in the output file first:
        buff.put(sb.toString().getBytes());

        //create the FileChannels:
        inChan  = new RandomAccessFile(infile,  "r" ).getChannel();
        outChan = new RandomAccessFile(outfile, "rw").getChannel();

        //read the infile in to the buffer:
        inChan.read(buff);

        // prep the buffer:
        buff.flip();

        // write the buffer out to the file via the FileChannel:
        outChan.write(buff);
        inChan.close();
        outChan.close();
     } catch...etc

}

使用trasferTo(或transferFrom):

boolean concatFiles(StringBuffer sb, File infile, File outfile) {

    FileChannel inChan = null, outChan = null;

    try {

        //write the stringBuffer so it goes in the output file first:    
        PrintWriter  fw = new PrintWriter(outfile);
        fw.write(sb.toString());
        fw.flush();
        fw.close();

        // create the channels appropriate for appending:
        outChan = new FileOutputStream(outfile, true).getChannel();
        inChan  = new RandomAccessFile(infile, "r").getChannel();

        long startSize = outfile.length();
        long inFileSize = infile.length();
        long bytesWritten = 0;

        //set the position where we should start appending the data:
        outChan.position(startSize);
        Byte startByte = outChan.position();

        while(bytesWritten < length){ 
            bytesWritten += outChan.transferFrom(inChan, startByte, (int) inFileSize);
            startByte = bytesWritten + 1;
        }

        inChan.close();
        outChan.close();
    } catch ... etc

解决方法:

transferTo()效率更高,因为数据复制较少,如果可以全部在内核中完成,则无效率.而且,如果它不在您的平台上,它仍然会使用经过高度调整的代码.

您确实需要循环,有一天它将循环并且您的代码将继续工作.

标签:bytebuffer,filechannel,concatenation,nio,java
来源: https://codeday.me/bug/20191208/2091108.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有