打印字符串时出现内存不足错误

时间:2011-11-05 06:59:59

标签: java android

我有一个问题,我在通过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

3 个答案:

答案 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错误,在这种情况下发送帖子时会出现请求服务器。