简体   繁体   中英

java.lang.OutOfMemoryError while downloading file

I'm trying to download file at my android device. This is my code:

InputStream in = null;
ByteArrayOutputStream out = null;
FileOutputStream fos = null;

try {
    URL link = new URL(fileURL);
    in = new BufferedInputStream(link.openStream());
    out = new ByteArrayOutputStream();
    byte[] buf = new byte[8192];
    int n, bytesBuffered = 0;
    while (-1 != (n = in.read(buf))) {
        bytesBuffered += n;
        out.write(buf, 0, n);
        if (bytesBuffered >1048576) {
            bytesBuffered = 0;
            out.flush();
        }
    }
    byte[] response = out.toByteArray();
    fos = new FileOutputStream(filePath);
    fos.write(response);
    return true;

} catch (Throwable e) {
    e.printStackTrace();
    return false;
} finally {
//closing streams
}

It fails at out.write(buf, 0, n); with out of memory error. What is wrong? I've read I'm able to set bigger heap size at manifest, but I don't find it a good solution. What is wrong?

You are doing it wrong!

Open your FileOutputStream and just read from the input and copy it to the output stream:

private static final int BUFSIZE = 8096;

//

final byte[] buf = new byte[BUFSIZE];

int nrBytes;

while ((nrBytes = in.read(buf)) != -1)
    out.write(buf, 0, nrBytes);

(note: closing descriptors not handled here, left as an exercise; but sicne this is Android and you therefore don't have try-with-resource or even JSR 203, I suggest you use Guava and its Closer )

if your goal is to write the content on a file, there is no need to read the content in memory before writing it.

fos = new FileOutputStream(filePath);
while (-1 != (n = in.read(buf))) {
    bytesBuffered += n;
    fos.write(buf, 0, n);
}
fos.flush();

and I would also add a finally clause to the try block to close fos. The finally block is call either if you return successfully or if an error occurs. This way you will not leak the FileOutputStream

You need a do instead of a while loop :

do {    
    n = in.read(buf); 
    bytesBuffered += n;
    out.write(buf, 0, n);
    if (bytesBuffered >1048576) {
        bytesBuffered = 0;
        out.flush();
    }
} while (n != -1)

and also add a finally block as pointed out by tony

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM