How to write a potentially huge InputStream to File?
Asked Answered
M

2

13

I have an API call that returns a byte array. I currently stream the result into a byte array then make sure the checksums match and then write the ByteArrayOutputStream to File. The code is something like this and it works pretty well.

    String path = "file.txt";
    ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];
    int len = 0;
    while ((len = inputStream.read(buffer)) != -1) {
        byteBuffer.write(buffer, 0, len);
    }
    FileOutputStream stream = new FileOutputStream(path); 
    stream.write(byteBuffer.toByteArray());

My concern i that the result from inputstream could potentially be larger than the heap size in android and I could get OutOfMemory exceptions if the entire byte array is in memory. What is the most elegant way to write the inputStream to file in chunks, such that the byte array is never larger than the heap size?

Mcniel answered 28/3, 2012 at 15:23 Comment(2)
you suggesting my concern is irrelevant?Mcniel
Just eliminate the use of ByteArrayOutputStream. (I read it wrong .. my use it at all?)Whitmire
M
10

I went with the advice to skip the ByteArrayOutputStream and write to the FileOutputStream and this seems to address my concerns. With one quick adjustment, where the FileOutputStream is decorated by a BufferedOutputStream

String path = "file.txt";
OutputStream stream = new BufferedOutputStream(new FileOutputStream(path)); 
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = is.read(buffer)) != -1) {
    stream.write(buffer, 0, len);
}
if(stream!=null)
    stream.close();
Mcniel answered 28/3, 2012 at 19:36 Comment(2)
isn't is supposed to be the FileInputStream ? It's undefinedOvershoe
what's the benefit of use BufferedOutputStream instead of use directly FileOutputStream ?Microclimate
A
15

Don't write to the ByteArrayOutputStream. Write directly to the FileOutputStream.

String path = "file.txt";
FileOutputStream output = new FileOutputStream(path); 
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
    output.write(buffer, 0, len);
}
Astylar answered 28/3, 2012 at 15:25 Comment(3)
hmmm I guess that makes sense.Mcniel
I went with this OutputStream output = new BufferedOutputStream(new FileOutputStream(path)); after reading the FileOutputStream docs.Mcniel
Feel free to edit my answer to reflect that, and accept it. Otherwise, you can/should post & accept your own answer.Astylar
M
10

I went with the advice to skip the ByteArrayOutputStream and write to the FileOutputStream and this seems to address my concerns. With one quick adjustment, where the FileOutputStream is decorated by a BufferedOutputStream

String path = "file.txt";
OutputStream stream = new BufferedOutputStream(new FileOutputStream(path)); 
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = is.read(buffer)) != -1) {
    stream.write(buffer, 0, len);
}
if(stream!=null)
    stream.close();
Mcniel answered 28/3, 2012 at 19:36 Comment(2)
isn't is supposed to be the FileInputStream ? It's undefinedOvershoe
what's the benefit of use BufferedOutputStream instead of use directly FileOutputStream ?Microclimate

© 2022 - 2024 — McMap. All rights reserved.