如何修复OutOfMemoryError android studio

时间:2016-12-15 22:28:11

标签: java android zip out-of-memory 7zip

我有一个提取7zip文件的应用程序 我使用这两个lib来提取

  

compile'org.apache.commons:commons-compress:1.12'

     

编译文件('libs / xz-1.3.jar')

这是我的代码

      public void unzip() {
    try  {
        File fc = new File(_location,"Driver2.7z");
        System.out.println("file size"+fc.length());
        //File fd = new File(_location,"Driver2.bin");
        SevenZFile sevenZFile = new SevenZFile(fc);
        SevenZArchiveEntry entry = sevenZFile.getNextEntry();
        System.out.println( "Unzipping " );
        while(entry!=null){
            System.out.println(entry.getName());
            FileOutputStream out = new FileOutputStream(_location + entry.getName());
            //FileOutputStream out = new FileOutputStream(entry.getName());
            System.out.println(entry.getName());
            byte[] content = new byte[(int) entry.getSize()];
            System.out.println(entry.getName());
            sevenZFile.read(content, 0, content.length);
            System.out.println(entry.getName());
            out.write(content);
            System.out.println(entry.getName());
            out.close();
            entry = sevenZFile.getNextEntry();
            System.out.println(entry.getName());
        }
        sevenZFile.close();

        Log.d("Unzip", "Unzipping complete. path :  " +_location );
    } catch(Exception e) {
        System.out.println("Decompress"+ "unzip"+ e.getMessage());
    }

}

使用此代码我在某些设备上出现此错误

 E/AndroidRuntime: FATAL EXCEPTION: Thread-218
                                                              Process: ir.milano.driver, PID: 30164
                                                              java.lang.OutOfMemoryError: Failed to allocate a 137881308 byte allocation with 4194304 free bytes and 129MB until OOM
                                                                  at com.darkgamers.pepsiman.browser.mainmenu.DecompressFast.unzip(DecompressFast.java:38)
                                                                  at ir.milano.driver.CopyFiles$1.run(CopyFiles.java:75)

问题在于这一行

  

byte [] content = new byte [(int)entry.getSize()];

2 个答案:

答案 0 :(得分:3)

您正试图从zip中提取大文件,~130MB。你不应该通过分配一个大的连续字节块来做到这一点。相反,你应该使用Streams。

流不会立即打开整个内容,而只是跟踪文件中的位置,允许一次只读取文件的一部分。您已经有了输出流FileOutputStream,您只需要找到相关的API调用来获取输入流并研究从输入流到输出的复制。

或者,如果没有提供Stream API,您可以使用sevenZFile.read以更小的缓冲区读取和写入多个块。

byte[] content = new byte[16 * 1024]; //fixed reasonable size buffer
while((int noBytesRead = sevenZFile.read(content, 0, content.size()) != -1){
   //write the noBytesRead from content into your stream.
}

答案 1 :(得分:1)

不要将整个Zip条目内容加载到内存中。以块为单位复制内容。 4K的缓冲区大小shown在测试中效率很高。

另外,请使用try-with-resourcesenhanced for循环。

byte[] buffer = new byte[4096];
try (SevenZFile sevenZFile = new SevenZFile(fc)) {
    for (SevenZArchiveEntry entry : sevenZFile.getEntries()) {
        try (FileOutputStream out = new FileOutputStream(_location + entry.getName())) {
            for (int len; (len = sevenZFile.read(buffer)) > 0; ) {
                out.write(buffer, 0, len);
            }
        }
    }
}