Outofmemoryerror ByteArrayOutputStream将大文件发送到WS

时间:2012-08-31 06:58:01

标签: android out-of-memory bytearrayoutputstream

即时发送视频到网络服务并且可以正常使用不到10MB的视频,如果视频大约是12MB,则会给我带来错误的错误:

这是我的代码:

 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
                }

我认为这是因为我正在缓冲所有视频,但我不知道如何在没有缓冲区的情况下发送它。

这是堆栈错误:

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)

702行是dos.write(buffer,0,bufferSize);

有什么方法可以发送视频吗?谢谢

3 个答案:

答案 0 :(得分:3)

ByteArrayOutputStream默认情况下通过分配32个字节或构造函数指定的内存量开始。填充该缓冲区后,ByteArrayOutputStream 加倍缓冲区的大小。对于大型物体,这可能是一个真正的问题。你最好的选择是

  1. 使用构造函数指定的缓冲区大小或
  2. 扩展ByteArrayOutputStream并覆盖write方法,以便重新分配对您的流更有利。

答案 1 :(得分:1)

您可以尝试使用库类来执行此操作,而不是编写代码来自行复制流。

在Guava中,ByteStreams类可用。如果您是Commons IO类型的人,那就是IOUtils

在IOUtils中,您的代码看起来像这样:

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

我遗漏了必要的异常处理和流关闭。

答案 2 :(得分:1)

发生这种情况是因为 - 如果事先知道体长,则 setFixedLengthStreamingMode(int)时,如果设置了 setChunkedStreamingMode(int)。 在这种情况下,HttpURLConnection被强制在传输之前缓冲内存中的完整请求主体,浪费(并且可能耗尽)堆并增加延迟。 在链接中解释得很好 - http://developer.android.com/reference/java/net/HttpURLConnection.html

请在代码中添加以下行 - 。HttpUrlConnectionObject的 setChunkedStreamingMode(MAXBUFFERSIZE);  对于默认系统值设置0 HttpUrlConnectionObject.setChunkedStreamingMode(0);

这适合我。