Outofmemoryerror ByteArrayOutputStream sending large file to WS
Asked Answered
F

3

0

im sending videos to webservice and works ok with videos less than 10MB, if the video is about 12MB give me outofmemoryerror:

This is my code:

 FileInputStream fileInputStream = new FileInputStream(fichero);

                int bytesAvailable = fileInputStream.available();
                int maxBufferSize = 1024 * 1024 * 2;
                int bufferSize = Math.min(bytesAvailable, maxBufferSize);
                byte[] buffer = new byte[bufferSize];

                int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                while (bytesRead > 0) {
                    dos.write(buffer, 0, bufferSize);
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    // nuevos
                    byte byt[] = new byte[bufferSize];
                    fileInputStream.read(byt);

                    // nuevos
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                    // esto es nuevo
                    dos.write(buffer, 0, bufferSize);
                    // ya no es nuevo
                }

I think it is because im buffering all video, but i dont know how to send this without saviing in buffer.

This is the stack error:

08-31 08:54:20.925: E/AndroidRuntime(18476): Caused by: java.lang.OutOfMemoryError
08-31 08:54:20.925: E/AndroidRuntime(18476):    at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:91)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:216)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at org.apache.harmony.luni.internal.net.www.protocol.http.RetryableOutputStream.write(RetryableOutputStream.java:60)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at java.io.DataOutputStream.write(DataOutputStream.java:99)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at com.reparalia.movilidad.AdjuntarFicheros$SubeFichero.doInBackground(AdjuntarFicheros.java:702)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at com.reparalia.movilidad.AdjuntarFicheros$SubeFichero.doInBackground(AdjuntarFicheros.java:1)

The 702 line is dos.write(buffer, 0, bufferSize);

There are any way to send the video?Thanks

Folio answered 31/8, 2012 at 6:58 Comment(0)
P
3

ByteArrayOutputStream starts out by allocating either 32 bytes or a constructor-specified amount of memory by default. When that buffer has been filled-up, ByteArrayOutputStream doubles the size of the buffer. For large objects, this can be a real problem. Your best alternative is to either

  1. Make use of the constructor-specified buffer size, or
  2. Extend ByteArrayOutputStream and override the write methods so that reallocation is more advantageous for your stream.
Premundane answered 28/11, 2012 at 14:24 Comment(0)
J
1

Instead of writing the code to copy the stream yourself, you might try using a library class to do it.

In Guava, the ByteStreams class is available. If you're a Commons IO kind of person, there's IOUtils.

In IOUtils, your code would look something like this:

FileInputStream fileInputStream = new FileInputStream(fichero);
OutputStream dos = ...
IOUtils.copy(fileInputStream, dos);

I've left out the necessary exception handling and stream closing.

Joey answered 31/8, 2012 at 7:34 Comment(3)
can you give me a example usin ioutils please? I dont know how can i do it. ThanksFolio
This copy me 0 bytes into dos :SFolio
Using guava library dont get outofmemoryerror but the file is corrupted when arrive to server.Folio
T
1

This is happening because - If neither setFixedLengthStreamingMode(int) when the body length is known in advance, nor setChunkedStreamingMode(int) is set. In that case HttpURLConnection is forced to buffer the complete request body in memory before it is transmitted, wasting (and possibly exhausting) heap and increasing latency. Very well explained in the link - http://developer.android.com/reference/java/net/HttpURLConnection.html

Kindly add below line to your code - HttpUrlConnectionObject.setChunkedStreamingMode(maxBufferSize); for default system value set 0 HttpUrlConnectionObject.setChunkedStreamingMode(0);

This works for me.

Tyler answered 9/6, 2014 at 8:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.