我在某些设备上下载文件时遇到了一些麻烦,我收到了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。
答案 0 :(得分:1)
你有许多你不需要的缓冲区。
byte[] br = readingfile.toByteArray();
您正在使用numberOfBytesReaded
。inputStream = ... readingfile.toByteArray());
并将其复制到第三个缓冲区byte data[] = new byte[bufferSize];
。尝试仅对所有这些操作使用一个。
一般建议是在不再需要它时将对象(和数组)的指针设置为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();
}
}