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

时间:2014-02-06 10:04:05

标签: android file out-of-memory large-files

我在某些设备上下载文件时遇到了一些麻烦,我收到了OOM错误。这是我用来下载大文件的代码:

/**
 * 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 个答案:

答案 0 :(得分:1)

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

  1. byte[] br = readingfile.toByteArray();您正在使用numberOfBytesReaded
  2. 然后你再次获得阵列:inputStream = ... readingfile.toByteArray()); 并将其复制到第三个缓冲区
  3. byte data[] = new byte[bufferSize];
  4. 尝试仅对所有这些操作使用一个。

    一般建议是在不再需要它时将对象(和数组)的指针设置为NULL

    我会使用这样的代码:

    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();
        }
    }