【问题标题】:Byte[] and java.lang.OutOfMemoryError reading file by bitsByte[] 和 java.lang.OutOfMemoryError 逐位读取文件
【发布时间】:2012-03-19 06:53:55
【问题描述】:

我正在尝试编写一个按位读取文件的阅读器,但我遇到了大文件的问题。我尝试读取 100 mb 的文件,花了 3 多分钟,但它成功了。

但是,然后我尝试了 500 mb 的文件,但它甚至没有启动。因为这条线:

byte[] fileBits = new byte[len];

现在我正在寻找解决方案,但找不到任何解决方案。 也许有人已经解决了它并可以分享一些代码、提示或想法。

if (file.length() > Integer.MAX_VALUE) {
    throw new IllegalArgumentException("File is too large: " + file.length());
}

int len = (int) file.length();
FileInputStream inputStream = new FileInputStream(file);

try {
    byte[] fileBits = new byte[len];
    for (int pos = 0; pos < len;) {
        int n = inputStream.read(fileBits, pos, len - pos);
        if (n < 0) {
            throw new EOFException();
        }
        pos += n;
    }

inputStream.read(fileBits, 0, inputStream.available());
inputStream.close();

【问题讨论】:

  • 您真的需要一次完整的文件吗?是什么阻止您流式传输?
  • 你试过searchingOutOfMemoryError 吗?见java -mx
  • 您创建的每个索引都是 4 个字节。其中 5 亿将尝试分配 2G 的空间。如果没有更多内存或 josh.trow 建议的缓冲区/流式处理,您无法以这种方式解决它
  • 当我们的应用程序内存不足时,对我们有用的解决方案是使用具有 96GB RAM(带有适当的 -XMx 选项)而不是 24GB 的机器.. :D.. 说真的,尽管回答什么乔希说..
  • @JohnVint 创建byte 数组如何使用每个索引超过一个字节?

标签: java file memory file-io


【解决方案1】:

我建议你试试内存映射。

FileChannel fc = new FileInputStream(file).getChannel();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, (int) fc.size());

这将使整个文件几乎立即可用(大约 10 毫秒)并且几乎不使用堆。顺便说一句,该文件必须小于 2 GB。

【讨论】:

    【解决方案2】:

    如果你真的需要一次将整个文件加载到内存中,我只能建议增加 Java 可用的内存。尝试使用Xmx(最大堆大小)或Xms(初始堆大小)参数调用您的程序(如果您事先知道需要多少内存,请使用后者,否则前者可能是最好的)。

    java -Xms512m -Xmx1g BigApp
    

    您也可以使用蔚来的Memory-mapped files

    【讨论】:

      【解决方案3】:

      您不应该将整个文件打开到内存中。您需要创建一个固定大小的字节数组缓冲区,然后从您定义的大小的块中打开文件。

      【讨论】:

        【解决方案4】:

        我建议你使用RandomAccessFile

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-07-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多