当前位置: 首页 > 面试题库 >

合并大文件而不将整个文件加载到内存中?

常炯
2023-03-14
问题内容

我想将包含字符串的巨大文件合并为一个文件,并尝试使用nio2。我不想将整个文件加载到内存中,因此我尝试了BufferedReader:

public void mergeFiles(filesToBeMerged) throws IOException{

Path mergedFile = Paths.get("mergedFile");
Files.createFile(mergedFile);

List<Path> _filesToBeMerged = filesToBeMerged;

try (BufferedWriter writer = Files.newBufferedWriter(mergedFile,StandardOpenOption.APPEND)) {
        for (Path file : _filesToBeMerged) {
// this does not work as write()-method does not accept a BufferedReader
            writer.append(Files.newBufferedReader(file));
        }
    } catch (IOException e) {
        System.err.println(e);
    }

}

我对此进行了尝试,但是,它的工作原理,字符串的格式(例如,新行等未复制到合并文件中):

...
try (BufferedWriter writer = Files.newBufferedWriter(mergedFile,StandardOpenOption.APPEND)) {
        for (Path file : _filesToBeMerged) {
//              writer.write(Files.newBufferedReader(file));
            String line = null;


BufferedReader reader = Files.newBufferedReader(file);
            while ((line = reader.readLine()) != null) {
                    writer.append(line);
                    writer.append(System.lineSeparator());
             }
reader.close();
        }
    } catch (IOException e) {
        System.err.println(e);
    }
...

如何在不将整个文件加载到内存的情况下将大型文件与NIO2合并?


问题答案:

如果您想有效地合并两个或多个文件,则应问自己,为什么要使用char基础文件ReaderWriter执行该任务。

通过使用这些类,您可以将文件的字节转换为字符,从系统的默认编码转换为unicode,然后从unicode转换回系统的默认编码。这意味着程序必须对整个文件执行两次数据转换。

而且,顺便说一句,BufferedReaderBufferedWriter绝不是NIO2假象。这些类自Java的第一个版本以来就存在。

当您通过实际的NIO函数使用字节方式复制时,文件可以被传输,而不会被Java应用程序所触摸,在最佳情况下,传输将直接在文件系统的缓冲区中进行:

import static java.nio.file.StandardOpenOption.*;

import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;

public class MergeFiles
{
  public static void main(String[] arg) throws IOException {
    if(arg.length<2) {
      System.err.println("Syntax: infiles... outfile");
      System.exit(1);
    }
    Path outFile=Paths.get(arg[arg.length-1]);
    System.out.println("TO "+outFile);
    try(FileChannel out=FileChannel.open(outFile, CREATE, WRITE)) {
      for(int ix=0, n=arg.length-1; ix<n; ix++) {
        Path inFile=Paths.get(arg[ix]);
        System.out.println(inFile+"...");
        try(FileChannel in=FileChannel.open(inFile, READ)) {
          for(long p=0, l=in.size(); p<l; )
            p+=in.transferTo(p, l-p, out);
        }
      }
    }
    System.out.println("DONE.");
  }
}


 类似资料:
  • 问题内容: 我只想从Excel文件(xlsx)中读取10行,而不一次加载整个文件,因为这不能在我的一台计算机上完成(内存不足)。 我尝试使用 看来文件先被加载然后又被分成几部分。 如何只读取第一行? 问题答案: 由于文件的性质(本质上是一堆压缩在一起的文件),您不能将文件戳到任意字节,而希望它成为您感兴趣的表中表格的第N行的开头。 你能做的最好是用与(从文件顶部跳过行)和(从底部跳跃行)参数。但是

  • 我们使用Apache Camel来压缩和解压缩我们的文件。我们使用标准的和API。 我们的问题是,当我们得到非常大的文件(例如800MB到1GB以上的文件大小)时,我们的应用程序将耗尽内存,因为整个文件被加载到内存中进行压缩和解压缩。 是否有任何骆驼API或java库可以帮助压缩/解压缩文件,而不需要将整个文件加载到内存中。 这里还有一个类似的未解问题

  • 问题内容: 我经常使用Scanner类来读取文件,因为它非常方便。 我的问题是,以上语句是否一次将整个文件加载到内存中?或者在fileScanner上进行后续调用,例如 从文件中读取(即从外部存储而不是从内存中读取)?我问是因为我担心如果文件太大而无法一次全部读入内存会发生什么。谢谢。 问题答案: 如果您阅读了源代码,则可以自己回答问题。 看来所讨论的Scanner构造函数的实现显示: 后者包装在

  • 问题内容: 我需要逐行读取一个大文件。可以说该文件的大小超过5GB,我需要读取每一行,但是显然我不想使用它,因为它将在内存中创建一个非常大的列表。 下面的代码在这种情况下将如何工作?自身是否一一读取到内存中?是否需要生成器表达式? 另外,与命令一样,我该怎么做才能以相反的顺序阅读? 问题答案: 我提供此答案是因为Keith的提示虽然简洁,但并未明确关闭文件

  • 问题内容: 我在Web应用程序中使用jquery,我需要将更多jquery脚本文件加载到单个页面中。 Google建议我将所有jquery脚本文件合并到一个文件中。 我怎样才能做到这一点? 问题答案: 在Linux上,您可以使用简单的Shell脚本将多个javascript文件合并为一个。它利用了Closure Compiler在线服务,因此生成的脚本也得到了有效压缩。

  • 如果我有一些文件,每个文件都有一个页面,我想使用 我在这里读到了几十个关于相同的问题,但大多数问题都已经过时或不再适用于