178 votes

Comment créer un fichier zip en Java

J'ai un fichier texte dynamique qui extrait le contenu d'une base de données en fonction de la requête de l'utilisateur. Je dois écrire ce contenu dans un fichier texte et le zipper dans un dossier dans une servlet. Comment dois-je m'y prendre ?

294voto

Chris Points 4552

Regardez cet exemple :

StringBuilder sb = new StringBuilder();
sb.append("Test String");

File f = new File("d:\\test.zip");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f));
ZipEntry e = new ZipEntry("mytext.txt");
out.putNextEntry(e);

byte[] data = sb.toString().getBytes();
out.write(data, 0, data.length);
out.closeEntry();

out.close();

Cela va créer un zip dans la racine de D: nommé test.zip qui contiendra un seul fichier appelé mytext.txt . Bien sûr, vous pouvez ajouter d'autres entrées zip et également spécifier un sous-répertoire comme ceci :

ZipEntry e = new ZipEntry("folderName/mytext.txt");

Vous pouvez trouver plus d'informations sur la compression avec Java aquí .

2 votes

Pourquoi les deux lignes : byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length); inclus dans cet exemple de code ? Quel est leur objectif ?

0 votes

@kdzia, la première ligne convertit la valeur StringBuilder en un tableau d'octets, et la deuxième ligne prend ce tableau d'octets et l'écrit dans l'entrée Zip du fichier "test.zip". Ces lignes sont nécessaires car les fichiers Zip fonctionnent avec des tableaux d'octets, pas avec des chaînes de caractères.

4 votes

Mais... dans l'exemple ci-dessus, comment le StringBuilder peut-il contenir autre chose que "Test String" ? Je ne comprends pas bien non plus. Si vous écrivez le sb.toString().getBytes() au fichier ZIP, je suppose que vous voulez qu'il contienne les octets du fichier que vous zippez ? Ou est-ce que j'ai oublié quelque chose ?

157voto

Siva Points 31

Java 7 a intégré ZipFileSystem, qui peut être utilisé pour créer, écrire et lire des fichiers à partir de fichiers zip.

Doc Java : Fournisseur de système de fichiers zip

Map<String, String> env = new HashMap<>();
// Create the zip file if it doesn't exist
env.put("create", "true");

URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip");

try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
    Path externalTxtFile = Paths.get("/codeSamples/zipfs/SomeTextFile.txt");
    Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt");          
    // Copy a file into the zip file
    Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING); 
}

2 votes

Existe-t-il un moyen de faire fonctionner ce système si l'extension n'est pas .zip ? J'ai besoin d'écrire un .foo qui est formaté exactement comme un fichier zip, mais avec une extension différente. Je sais que je peux faire un .zip et le renommer, mais il serait plus simple de le créer avec le bon nom.

4 votes

@TroyDaniels l'exemple ci-dessus fonctionne aussi avec une extension différente, puisqu'il utilise jar:file: pour créer l'URI.

12 votes

Le seul problème qui peut apparaître ici est que cela ne fonctionnera pas si vous avez des répertoires. Ainsi, par exemple, si vous avez "/dir/SomeTextFile.txt" dans le fichier pathInZipfile vous devez créer le "dir" à l'intérieur de l'archive .zip. Pour cela, il suffit d'ajouter la ligne suivante : Files.createDirectories(pathInZipfile.getParent()) avant d'invoquer Files.copy méthode.

42voto

Neyas Points 151

Pour écrire un fichier ZIP, vous utilisez un ZipOutputStream. Pour chaque entrée que vous souhaitez placer dans le fichier ZIP, vous créez un objet ZipEntry. Vous passez le nom du fichier au constructeur de ZipEntry ; celui-ci définit les autres paramètres tels que la date du fichier et la méthode de décompression. Vous pouvez remplacer ces paramètres si vous le souhaitez. Ensuite, vous appelez la méthode putNextEntry du ZipOutputStream pour commencer à écrire un nouveau fichier. Envoyez les données du fichier au flux ZIP. Lorsque vous avez terminé, appelez la méthode closeEntry. Répétez l'opération pour tous les fichiers que vous souhaitez stocker. Voici un squelette de code :

FileOutputStream fout = new FileOutputStream("test.zip");
ZipOutputStream zout = new ZipOutputStream(fout);
for all files
{
    ZipEntry ze = new ZipEntry(filename);
    zout.putNextEntry(ze);
    send data to zout;
    zout.closeEntry();
}
zout.close();

28voto

Owen Tsao Points 1262

Voici un exemple de code pour compresser un répertoire complet (y compris les sous-fichiers et les sous-répertoires), il utilise la fonction d'arborescence de fichiers de Java NIO.

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipCompress {
    public static void compress(String dirPath) {
        final Path sourceDir = Paths.get(dirPath);
        String zipFileName = dirPath.concat(".zip");
        try {
            final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
            Files.walkFileTree(sourceDir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) {
                    try {
                        Path targetFile = sourceDir.relativize(file);
                        outputStream.putNextEntry(new ZipEntry(targetFile.toString()));
                        byte[] bytes = Files.readAllBytes(file);
                        outputStream.write(bytes, 0, bytes.length);
                        outputStream.closeEntry();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Pour l'utiliser, il suffit d'appeler

ZipCompress.compress("target/directoryToCompress");

et vous obtiendrez un fichier zip répertoireToCompress.zip

1 votes

Comment inclure le répertoire actuel ?

0 votes

Il compresse également le fichier zip à nouveau si les répertoires d'entrée et de sortie sont les mêmes.

7voto

Pavel Points 109

Dossier unique :

String filePath = "/absolute/path/file1.txt";
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    File fileToZip = new File(filePath);
    zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
    Files.copy(fileToZip.toPath(), zipOut);
}

Fichiers multiples :

List<String> filePaths = Arrays.asList("/absolute/path/file1.txt", "/absolute/path/file2.txt");
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    for (String filePath : filePaths) {
        File fileToZip = new File(filePath);
        zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
        Files.copy(fileToZip.toPath(), zipOut);
    }
}

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