当前位置: 首页 > 知识库问答 >
问题:

文件下载-内存不足(OOM)

呼延子安
2023-03-14
/**
 * The size of the chunks that an file is split when writing to server.<br />
 * 1024 * 1024 -> 1mb
 */
private static final int CHUNK_SIZE = 1024 * 1024;

File output = new File(sdCardPath, fileName);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(output);
} catch (FileNotFoundException e) {
e.printStackTrace();
}

int offset = 0;

// compute the number of chunks of 1 mb for downloading the file
// by parts
int parts = tmpFileSize / CHUNK_SIZE;
ByteString readingfile = null;
long progressUpdate = 0;

for (int partsCounter = 0; partsCounter < parts + 1; partsCounter++) {
    try {
        readingfile = serviceApi
                .readFile(
                        session,
                        filehandle, offset, CHUNK_SIZE);

        byte[] bytesRead = readingfile.toByteArray();
        int numberOfBytesReaded = bytesRead.length;
        offset = offset + numberOfBytesReaded;
        progress.publish(""
                + (int) ((progressUpdate * 100) / tmpFileSize));
        progressUpdate += numberOfBytesReaded;
        fileOutputStream.write(bytesRead, 0,
                numberOfBytesReaded);

    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

try {
    if (null != fileOutputStream) {
        fileOutputStream.flush();
        fileOutputStream.close();
    }
} catch (IOException e) {
    e.printStackTrace();
}

基于@ari答案的解决方案我已经更新了代码。现在它被优化到只使用1MB(我不知道这是否是将进程分成块的最佳方式,但现在它似乎得到了改进,并且不提供OOM)。我将尝试通过检测可以使用多少堆内存来进一步优化它,但我不确定是否可以实现这一点。直到比这似乎是最好的选择。再次感谢@Ari。

共有1个答案

郜卓君
2023-03-14

您有许多不需要的缓冲区。

  1. byte[]br=readingfile.tobytearray();用于获取numberofbytesreaded.
  2. 然后再次获得数组:inputstream=...readingfile.tobytearray());并将其复制到第三个缓冲区
  3. 字节数据[]=新字节[bufferSize];.

尝试对所有这些操作只使用一个。

for (int partsCounter = 0; partsCounter < parts + 1; partsCounter++) {
    readingfile = serviceApi.readFile(session, filehandle, offset,
            (int) bufferSize);
    byte[] br = readingfile.toByteArray();
    int numberOfBytesReaded = br.length;
    offset = offset + numberOfBytesReaded;

    try {
            progress.publish(""
                    + (int) ((progressUpdate * 100) / tmpFileSize));
            progressUpdate += numberOfBytesReaded;
            fileOutputStream.write(br, 0, numberOfBytesReaded);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
 类似资料:
  • 我正在从命令行运行jmx

  • 我正在努力解决古老的字谜问题。多亏了许多教程,我能够迭代一组字符串,递归地找到所有的排列,然后将它们与英语单词列表进行比较。我发现的问题是,在大约三个单词之后(通常是关于“变形”之类的东西),我会得到一个OutOfMemory错误。我试着把我的批分成小的集合,因为它似乎是消耗我所有内存的递归部分。但即使只是“变形”也把它锁起来了... 编辑:根据出色的反馈,我已经将生成器从排列更改为工作查找: 它

  • 为了加载几个大的(~200MB) JSON文件,执行了以下代码: 以下是 Pycharm 的自定义 VM 选项的外观(最大 30GB 堆大小,RAM 为 32GB): 已应用“使缓存失效/重新启动”的流行建议。 加载2个文件(总计约400MB)后,在第三次加载期间,引发异常“MemoryError”。 我不明白为什么如果我有高达30GB的堆大小,内存错误抛出后只有400MB?

  • 问题内容: 我今天遇到一个奇怪的问题。对于其他人来说,这可能是一个简单的答案,但这让我感到困惑。为什么下面的代码会导致内存错误? 我得到了这两个错误之一…第一个是在节点的解释器中运行此代码时,第二个是通过nodeunit运行它时: 严重错误:CALL_AND_RETRY_2分配失败-内存不足 严重错误:JS分配失败-内存不足 问题答案: 当我尝试访问阵列时会发生这种情况。但是获取长度却没有。

  • 那是外部存储代码,但我想保存在Android手机的内部存储。

  • 问题内容: 从Apache Commons使用Base64 我正在为移动设备制作小型应用程序。 问题答案: 您不能像下面这样将整个文件加载到内存中: 而是逐块加载文件并对其进行部分编码。Base64是一种简单的编码,一次加载3个字节并对其进行编码就足够了(编码后将产生4个字节)。出于性能原因,请考虑加载3字节的倍数,例如3000字节- 应该很好。还可以考虑缓冲输入文件。 一个例子: 请注意,您不能