9 votes

Compresser un gros fichier dans un ZIP avec Java

J'ai besoin de compresser un grand fichier (~450 Mbyte) avec la classe Java ZipOutputStream. Cette grande dimension cause un problème d'erreur "OutOfMemory" de l'espace du tas de ma JVM. Cela se produit parce que la méthode "zos.write(...)" stocke TOUT le contenu du fichier à compresser dans un tableau interne d'octets avant de le compresser.

            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();

La solution naturelle sera d'agrandir l'espace mémoire du tas de la JVM, mais j'aimerais savoir s'il existe une méthode pour écrire ces données en continu. Je n'ai pas besoin d'un taux de compression élevé, donc je pourrais aussi changer l'algorithme.

Quelqu'un a-t-il une idée à ce sujet ?

11voto

jarnbjo Points 18238

D'après votre commentaire à la réponse de Sam, vous avez manifestement créé un ZipOutputStream, qui enveloppe un ByteArrayOutputStream. Le ByteArrayOutputStream met bien sûr en cache le résultat compressé en mémoire. Si vous voulez qu'il soit écrit sur le disque, vous devez envelopper le ZipOutputStream autour d'un FileOutputStream.

3voto

Carl Smotricz Points 36400

Il y a une bibliothèque appelée TrueZip que j'ai utilisé avec succès dans le passé pour faire ce genre de choses.

Je ne peux pas garantir qu'il fasse mieux en matière de mise en mémoire tampon. Mais je sais qu'il fait beaucoup de choses avec son propre codage plutôt que de dépendre de l'API Zip du JDK.

Cela vaut donc la peine d'essayer, à mon avis.

1voto

Sam Barnum Points 5019

ZipOutputStream est basé sur un flux, il ne conserve pas de mémoire. Votre BUFFER est peut-être trop grand.

0voto

cjstehno Points 3913

Je me demande si ce n'est pas parce que vous stockez le contenu dans une ZipEntry, peut-être qu'il charge tout son contenu avant d'écrire la ZipEntry. Êtes-vous obligé d'utiliser Zip ? Si vous n'avez besoin de compresser qu'un seul flux de données, vous pouvez envisager d'utiliser GZIPOutputStream. Je pense qu'il n'aurait pas le même problème.

J'espère que cela vous aidera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X