我有一个提取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()];
答案 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-resources和enhanced 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);
}
}
}
}