Reputation: 1579
I am using this segment of copy a large file. Android crashes with "out of memory" at exactly 32 buffer loads. It is acting like dos.write is putting the data into a large buffer rather than spooling it out to the i/o device. No exception is thrown.
The bufferSize = 512*1024. bis is a BufferedInputStream. byteArray is a ByteArrayBuffer,
try {
FileOutputStream fos = new FileOutputStream(file);
dos = new DataOutputStream(fos);
int current = 0;
while((current = bis.read()) != -1){
byteArray.append((byte)current);
if (byteArray.isFull()){
byte[] b = byteArray.toByteArray();
dos.write(b, 0, bufferSize);
byteArray.clear();
}
}
int count = byteArray.length();
byte[] b = byteArray.toByteArray();
dos.write(b, 0, count);
dos.flush();
dos.close();
bis.close();
}
catch (Exception e) {
RunTimeError("Exception: " + e);
return false;
}
Upvotes: 1
Views: 3315
Reputation: 234847
My guess is that byteArray.isFull()
is always returning false
for some reason. Then when you have loaded 16MB of data, you're out of memory. I wouldn't bother with a ByteArrayBuffer
. (For that matter, 512KB is way too large a buffer for this kind of operation. You should try to match the file I/O block size. It probably varies by device, but 4K-8K is probably close.) You also don't need to wrap fos
in a DataOutputStream
; you're just writing bytes. A BufferedOutputStream
, on the other hand, might be useful. And if bis
is not buffered, wrapping it in a BufferedInputStream
will also help.
I would rewrite your code like this:
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(file), 8192);
byte[] buffer = new byte[1024];
int len = 0;
while((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (Exception e) {
RunTimeError("Exception: " + e);
return false;
} finally {
try { bis.close(); } catch (Exception ignored) { }
try { bos.close(); } catch (Exception ignored) { }
}
Upvotes: 7