out of memory Error while writing ByteArrayOutputStream in Android
Solution 1
What you are doing isn't practical, but the way to do it is as follows:
File file = new File("/sdcard/E0022505.mp4");
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
byte[] fileData = new byte[file.length()];
int read = 0;
while(read != fileData.length) {
read += is.read(fileData, read, fileData.length - read);
}
//fileData now has all of the files bytes (don't forget to close is)
Solution 2
If you know how big your file is going to be, you'd probably want to seed the bytearrayoutputstream to that size (or slightly larger) in the constructor. I'm not 100% sure of the details, but I think BAOS creates a new array, and copies the old one in, each time 'expand' is called. Other implementations keep a list of arrays that are rebuilt when outputting. Either way, you don't want that (doubles memory usage, or worse).
new ByteArrayOutputStream(new File(Environment.getExternalStorageDirectory(), "E0022505.mp4").length());
Sanat Pandey
Updated on July 14, 2022Comments
-
Sanat Pandey almost 2 years
I have a big problem, that I am reading 2^21 bytes from a video file which resides in Sdcard but when we write the same in ByteArrayOutputStream it throws an Exception as Out of Memory. I don't know why? Please suggest the right solution for the same.
Here is the stack trace.
Error Stack:
11-03 19:24:23.193: ERROR/AndroidRuntime(28258): FATAL EXCEPTION: main 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): java.lang.OutOfMemoryError 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:93) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:218) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at com.example.TestCryptoActivity.onCreate(TestCryptoActivity.java:42) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at android.app.ActivityThread.access$2300(ActivityThread.java:125) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at android.os.Handler.dispatchMessage(Handler.java:99) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at android.os.Looper.loop(Looper.java:123) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at android.app.ActivityThread.main(ActivityThread.java:4627) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at java.lang.reflect.Method.invokeNative(Native Method) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at java.lang.reflect.Method.invoke(Method.java:521) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 11-03 19:24:23.193: ERROR/AndroidRuntime(28258): at dalvik.system.NativeStart.main(Native Method)
Code:
try { is = new FileInputStream("/sdcard/E0022505.mp4"); } catch (FileNotFoundException e2) { // TODO Auto-generated catch block e2.printStackTrace(); } ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; try { while ((bytesRead = is.read(b)) != -1) { bos.write(b, 0, bytesRead);//--------This position returns the same error } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } byte[] bytes = bos.toByteArray(); try { String byteString = new String(bytes,"UTF-8"); System.out.println("the bytes array of video:"+byteString); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }
-
Yar over 9 yearsSorry, but how is this supposed to fix OutOfMemoryError if you actually declare: byte[] fileData = new byte[file.length()]; so you load WHOLE FILE to memory?
-
Justin Breitfeller over 9 yearsWell this approach doesn't attempt to allocate another 2MB block as a string. But in general (and as I indicated in my answer) you want to avoid doing this if you can as it isn't practical. In his case, I assume there was a reason he wanted to load the entire file into memory. That really wasn't indicated here. I'm sure he figured this out 3 years ago though so its all really moot.
-
Alston over 9 yearsFor this instruction:
byte[] fileData = new byte[file.length()];
, if the file size is too large, memory leak would happened! -
Justin Breitfeller over 9 yearsIt wouldn't be a memory leak, but it could be an out of memory error if the allocation is too large. In this question, he was doing a 2 mb allocation which will probably succeed on most devices (depending on the other memory requirements in his app).
-
Prashant almost 9 yearsbyte[] fileData = new byte[file.length()]; this is not a correct solution, if the file is very big then it'll give the same outOfMemoryError. I've already tried this. Please provide a solution which is perfectly working.