我想创建一个zip文件来下载它。我有很多pdf文件..
我需要将它们压缩成50MB的子拉链,所以我创建了一个包含所有其他子拉链的主拉链..
但是当我运行我的代码时,我获得了:
Grave: Servlet.service() for servlet [appServlet] in context with path [/myProg] threw exception [Handler processing failed; nested exception is java.lang.OutOfMemoryError: Java heap space] with root cause
java.lang.OutOfMemoryError: Java heap space
这是我分割和压缩所有文件的代码:
public void zippatore(List<File> filesDaZippare, ZipOutputStream masterZos, String zipName, String pdfName) throws IOException{
float newSize = 0;
boolean first = true;
int count = 1;
File file;
ByteArrayOutputStream subBaos = new ByteArrayOutputStream();
ZipOutputStream subZos = new ZipOutputStream(subBaos);
masterZos.putNextEntry(new ZipEntry(zipName+" "+count++ +".zip"));
while(filesDaZippare.size() > 0){
file = filesDaZippare.remove(0);
FileInputStream fis = new FileInputStream(file);
newSize += file.length();
String fileName = file.getName().substring(2);
if(newSize < MAX_SIZE || first){
subZos.putNextEntry(new ZipEntry(pdfName+" "+fileName+".pdf"));
IOUtils.copy(fis, subZos);
file.delete();
subZos.closeEntry();
first = false;
}else{
subZos.flush();
subZos.close();
masterZos.write(subBaos.toByteArray());
masterZos.closeEntry();
masterZos.putNextEntry(new ZipEntry(zipName+" "+count++ +".zip"));
subZos = new ZipOutputStream(subBaos);
subZos.putNextEntry(new ZipEntry(pdfName+" "+fileName+".pdf"));
IOUtils.copy(fis, subZos);
file.delete();
newSize = file.length();
first = true;
}
subZos.closeEntry();
}
subZos.closeEntry();
subZos.flush();
subZos.close();
masterZos.write(subBaos.toByteArray());
masterZos.closeEntry();
}
我该如何解决?
修改 我添加了代码以保存在tmp文件夹中我的子zip文件..而且我这样做:
File folder = new File(VariabiliGlobali.PATH_TMP);
byte[] buffer = new byte[1024];
for(File file : folder.listFiles()) {
FileInputStream fis = new FileInputStream(file);
masterZos.putNextEntry(new ZipEntry(file.getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
masterZos.write(buffer, 0, length);
}
masterZos.closeEntry();
fis.close();
}
masterZos.flush();
masterZos.close();
获取所有zip文件并输入我的主zip文件,但是当我将它们放入其中时我得到了相同的错误...
答案 0 :(得分:4)
我这样解决了:
对于主zip文件我使用FileOutputStream
,而对于所有其他子zip文件我使用ByteArrayOutputStream
,我刷新并每50 MB关闭它。
所以我不对每个子zip使用文件,因此使用流比使用文件快一点..
这是代码:
FileOutputStream masterBos = new FileOutputStream(VariabiliGlobali.PATH_TMP+"Tmp.zip");
ZipOutputStream masterZos = new ZipOutputStream(masterBos);
public void zippatore(List<File> filesDaZippare, ZipOutputStream masterZos, String zipName, String pdfName) throws IOException{
float newSize = 0;
boolean first = true;
int count = 1;
File file;
ByteArrayOutputStream subBaos = new ByteArrayOutputStream();
ZipOutputStream subZos = new ZipOutputStream(subBaos);
masterZos.putNextEntry(new ZipEntry(zipName+" "+count++ +".zip"));
while(filesDaZippare.size() > 0){
file = filesDaZippare.remove(0);
FileInputStream fis = new FileInputStream(file);
newSize += file.length();
String fileName = file.getName().substring(2);
if(newSize < MAX_SIZE || first){
subZos.putNextEntry(new ZipEntry(pdfName+" "+fileName+".pdf"));
IOUtils.copy(fis, subZos);
file.delete();
subZos.closeEntry();
first = false;
}else{
subZos.flush();
subZos.close();
subBaos.flush();
subBaos.close();
masterZos.write(subBaos.toByteArray());
masterZos.closeEntry();
masterZos.putNextEntry(new ZipEntry(zipName+" "+count++ +".zip"));
subBaos = new ByteArrayOutputStream();
subZos = new ZipOutputStream(subBaos);
subZos.putNextEntry(new ZipEntry(pdfName+" "+fileName+".pdf"));
IOUtils.copy(fis, subZos);
file.delete();
newSize = file.length();
first = true;
}
subZos.closeEntry();
}
subZos.closeEntry();
subZos.flush();
subZos.close();
masterZos.write(subBaos.toByteArray());
masterZos.closeEntry();
}
答案 1 :(得分:2)
从代码中可以看出,您正在将每个子zip压缩到由ByteArrayOutput流支持的输出流中,这将消耗内存。将每个Sub文件写入磁盘上的临时位置,然后将单个zip压缩到主zip中将减少内存需求,同时写入磁盘有开销,但如果整体大小不知道这个会是一个更好的方法。
只要磁盘有足够的空间来处理它,就可以将临时zip / subzip写入FileOutputstream而不是ByteArrayOutputStream,这样就可以继续。
public void zippatore(List<File> filesDaZippare, ZipOutputStream masterZos, String zipName, String pdfName) throws IOException{
float newSize = 0;
boolean first = true;
int count = 1;
File file;
ByteArrayOutputStream subBaos = new ByteArrayOutputStream();
ZipOutputStream subZos = new ZipOutputStream(subBaos);
masterZos.putNextEntry(new ZipEntry(zipName+" "+count++ +".zip"));
while(filesDaZippare.size() > 0){
file = filesDaZippare.remove(0);
FileInputStream fis = new FileInputStream(file);
newSize += file.length();
String fileName = file.getName().substring(2);
if(newSize < MAX_SIZE || first){
subZos.putNextEntry(new ZipEntry(pdfName+" "+fileName+".pdf"));
IOUtils.copy(fis, subZos);
file.delete();
subZos.closeEntry();
first = false;
}else{
subZos.flush();
subZos.close();
masterZos.write(subBaos.toByteArray());
masterZos.closeEntry();
masterZos.putNextEntry(new ZipEntry(zipName+" "+count++ +".zip"));
subBaos = new ByteArrayOutputStream();
subZos = new ZipOutputStream(subBaos);
subZos.putNextEntry(new ZipEntry(pdfName+" "+fileName+".pdf"));
IOUtils.copy(fis, subZos);
file.delete();
newSize = file.length();
first = true;
}
subZos.closeEntry();
}
subZos.closeEntry();
subZos.flush();
subZos.close();
masterZos.write(subBaos.toByteArray());
masterZos.closeEntry();
}
答案 2 :(得分:0)
通过在服务器配置中指定VM参数来增加Java堆大小
例如:
-Xmx1024m
我在eclipse中运行Tomcat,你可以在其中指定VM参数 打开服务器配置的启动配置。