我有一个问题,我在通过Base64编码器将字节编码到String后打印字符串时遇到OuOfMemory错误。以下是与代码相关的详细信息:
错误堆栈:
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): FATAL EXCEPTION: main
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): java.lang.OutOfMemoryError
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:89)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at java.lang.StringBuffer.<init>(StringBuffer.java:83)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at com.example.TestCryptoActivity.onCreate(TestCryptoActivity.java:54)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at android.os.Handler.dispatchMessage(Handler.java:99)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at android.os.Looper.loop(Looper.java:123)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at android.app.ActivityThread.main(ActivityThread.java:4627)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at java.lang.reflect.Method.invokeNative(Native Method)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at java.lang.reflect.Method.invoke(Method.java:521)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-05 12:25:30.995: ERROR/AndroidRuntime(2660): at dalvik.system.NativeStart.main(Native Method)
代码(代码的最后一行负责错误):
File file = new File("/sdcard/E0022505.mp4");
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
byte[] fileData = new byte[2097152];
int read = 0;
while(read != fileData.length) {
try {
read += is.read(fileData, read, fileData.length - read);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(fileData,0,read);
bytes = bos.toByteArray();
StringBuffer strNew = new StringBuffer(Base64.encodeToString(fileData, 0));
System.out.println("The bytes array:"+strNew);---> This line makes error
答案 0 :(得分:1)
所以让我直截了当。你有一个大约2MB的文件,你想要base64编码(所以它将变成2.7MB),然后打印出来。
为什么呢?认真。你要检查输出的每个字节吗?
我会建议更多的内容:
System.out.println ("The bytes array:" + strNew.substring (0, 50));
所以你至少可以检查它而不会炸毁输出。
你的JRE(或者在这种情况下是Davlik)不太可能特别喜欢多兆字节字符串的想法(因为StringBuilder
是一切都在崩溃的地方这里)。
如果仍然没有帮助,您可以对base64编码进行分段,以便最终不会出现大字符串。 Base64将3n
个字节转换为4n
个字节,因此,如果您处理的是3的倍数,则不必担心对齐问题。例如,以3K块处理你的2M字节数组 - 每个数组都会给你一个4K base64编码的块来为你做些什么。而这种分块将减少内存不足的可能性。
答案 1 :(得分:0)
删除那些没有做任何有用的行,至少可以避免内存中至少2097152个字节:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(fileData,0,read);
bytes = bos.toByteArray();
对于其余部分,此代码会导致异常发生,但这可能是因为之前执行的代码的其他部分过于耗费内存。
尝试使用分析器来检测内存的使用位置。
但是将整个大字节数组及其在base64中编码的副本存储在android程序的内存中当然是个坏主意。
答案 2 :(得分:0)
Base64不是专门用于Android设备的,所以它永远不会考虑内存利用率,当我们编码视频文件时,字符串的长度也会很长,有时也会产生大图像,而且我们的臀部大小有限(25MB) )内存越来越大。
我多次遇到同样的问题,我确信其他人也有同时将大文件上传到服务器的Base64编码这是该死的很难的事情......在我的情况下我永远不会成功
我建议您更改服务器以接受字节数组中的数据,然后在Base64中接受数据。 在以字节为单位将文件发送到服务器时,使用多部分..有用的库是 http-mime4.1.1.jar
我已经阅读了这个问题的文档和博客,并花了很多天时间搜索解决方案..但是没有办法使用Base64有限的内存。如果你以编程方式克服了OOM错误,在这种情况下发送帖子时会出现请求服务器。