2009-11-20 4 views
8

zu komprimieren Ich habe eine große Datei (~ 450 Mbyte) durch die Java-Klasse ZipOutputStream komprimieren müssen. Diese große Dimension verursacht ein Problem des "OutOfMemory" -Fehlers meines JVM Heap Space. Dies geschieht, weil die Methode "zos.write (...)" den gesamten Dateiinhalt vor der Komprimierung in einem internen Byte-Array speichert.Um eine große Datei in einem ZIP mit Java

  origin = new BufferedInputStream(fi, BUFFER); 
     ZipEntry entry = new ZipEntry(filePath); 
     zos.putNextEntry(entry); 

     int count; 
     while ((count = origin.read(data, 0, BUFFER)) != -1) 
     { 
      zos.write(data, 0, count); 
     } 
     origin.close(); 

Die natürliche Lösung wird den Heap-Speicherplatz des JVM zu vergrößern, aber ich würde gerne wissen, ob es eine Methode ist, diese Daten in einer Streaming-Weise zu schreiben. Ich brauche keine hohe Kompressionsrate, damit ich den Algorithmus auch ändern kann.

hat jemand eine Idee?

+1

Wie groß ist PUFFER? –

+0

Wie ich schrieb 2048 – robob

Antwort

8

Entsprechend Ihrem Kommentar zu Sams Antwort haben Sie offensichtlich einen ZipOutputStream erstellt, der einen ByteArrayOutputStream umschließt. Der ByteArrayOutputStream speichert das komprimierte Ergebnis natürlich im Speicher zwischen. Wenn Sie es auf die Festplatte geschrieben haben möchten, müssen Sie den ZipOutputStream um einen FileOutputStream wickeln.

+0

Ok Ich verstehe, was Sie mir gesagt haben, aber die komprimierten Daten sind etwa 60 MByte ... tot niedrig, um einen "OutOfSpace" Heap-Fehler auszuführen. Was ist damit? Ich muss eine Xmx1024m einstellen, um gut zu sein! Wahrscheinlich ist mein Fehler! – robob

+2

+1, verwenden Sie einen FileOutputStream, um die Zip-Datei auf die Festplatte zu schreiben, oder verwenden Sie die HttpServletResponse-Ausgabestream, wenn Sie sie direkt an den Browser streamen möchten. –

+1

Wenn 60 MByte Speicher ausgelöscht wurden, haben Sie die JVM-Standardeinstellungen verwendet? Wenn ja, dann klingt das richtig. Selbst wenn Ihre JVM mit einer Heapgröße von 64 M ausgeführt wird, muss der ByteArrayOutputStream das Array byte [] erweitern, was eine vollständige Kopie bedeutet. – PSpeed

3

Es gibt eine Bibliothek namens TrueZip, die ich in der Vergangenheit mit gutem Erfolg benutzt habe, um so etwas zu tun.

Ich kann nicht garantieren, dass es auf der Pufferungsfront besser geht. Ich weiß, dass es viel mit seiner eigenen Kodierung macht und nicht abhängig von der Zip-API des JDK.

Also es ist meiner Meinung nach einen Versuch wert.

1

ZipOutputStream ist stream-basiert, es hält den Speicher nicht fest. Ihr PUFFER ist möglicherweise zu groß.

+0

Mein Puffer ist 2048 Byte und ich glaube nicht, ist zu groß! Dies ist die Ausnahme: Exception in thread "main" java.lang.OutOfMemoryError: Java Heap-Speicher \t bei java.util.Arrays.copyOf (Arrays.java:2786) \t bei java.io.ByteArrayOutputStream. write (ByteArrayOutputStream.java:94) \t bei java.util.zip.DeflaterOutputStream.deflate (DeflaterOutputStream.java:161) \t bei java.util.zip.DeflaterOutputStream.write (DeflaterOutputStream.java:118) \t bei Java .util.zip.ZipOutputStream.write (ZipOutputStream.java:272) – robob

0

Ich frage mich, ob es, weil Sie den Inhalt in einem ZipEntry speichern, vielleicht lädt es im Grunde alle seinen Inhalt vor dem Schreiben der ZipEntry. Müssen Sie Zip verwenden? Wenn es nur einen Datenstrom gibt, den Sie komprimieren müssen, schauen Sie stattdessen in den GZIPOutputStream. Ich glaube, dass es nicht das gleiche Problem hätte.

Hoffe, das hilft.

+0

Ich muss einen Verzeichnisinhalt in einer Zip-Datei speichern, um über Web Service – robob

+2

Sounds l zu senden Wenn Sie so große Objekte in Ihrer Antwort haben, ist das eine schlechte Idee. Ziehen Sie statt dessen eine URL zurück, von der die Zip-Datei abgerufen werden kann. Einfache Servlets ermöglichen eine Byte-basierte Streaming-Antwort. –

+0

Sie haben Recht Ich denke, das ist die richtige Wahl zu bekommen. – robob

Verwandte Themen