Xarph
Xarph

Reputation: 1579

Android, Data Output Stream, Out of memory

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

Answers (1)

Ted Hopp
Ted Hopp

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

Related Questions