IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ Fichiers, flux et réseauxConsultez toutes les FAQ

Nombre d'auteurs : 15, nombre de questions : 95, dernière mise à jour : 21 mars 2016  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur le forum Java de http://java.developpez.com ainsi que l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.

Sur ce, nous vous souhaitons une bonne lecture.

SommaireArchives (11)
précédent sommaire
 

De base, la JVM offre le support des formats d'archives suivants :

  • ZIP et GZIP - depuis le JDK 1.1 via les classes du package java.util.zip ;
  • JAR (Java Archive) - depuis le JDK 1.2 via les classes du package java.util.jar.


Les classes permettant de gérer le format JAR sont des extensions de celles permettant de gérer les formats ZIP et GZIP. Ainsi donc la majorité du code ci-après se trouve applicable pour le format JAR en utilisant les classes appropriées du package java.util.jar et sans procéder à plus de modifications. Le format JAR ajoute le support de la méthode de compression Pack200 qui permet de grandement réduire la taille des fichiers, la présence d'un fichier manifeste et d'attributs sur le contenu de l'archive ainsi que le support des signatures numériques.

Note : l'API standard ne prend pas en charge l’encryptage et le décryptage de contenu d'archives protégées par des mots de passe. Pour utiliser de telles fonctionnalités, vous devrez vous reposer sur des bibliothèques tierces telles que Zip4j, 7-Zip-JBinding, etc.

Mis à jour le 18 septembre 2015 bouye

La classe java.util.zip.ZipEntry (resp. java.util.jar.JarEntry) représente une entrée dans le catalogue des fichiers contenus dans l'archive ZIP (resp. JAR). Cette entité permet de manipuler les données du fichier référencé sous cette entrée tant lors de la création de l'archive que lors de la lecture de son contenu.

Chaque entrée dispose d'un nom unique constitué du chemin d’accès vers le fichier (arborescence des répertoires parents compris et en respectant la casse minuscule/majuscule) et dispose de plusieurs méthodes permettant de définir ou d'obtenir un commentaire, les méthodes, la taille du fichier non compressé, la taille du fichier compressé, le taux de compression, s'il s'agit d'un répertoire, etc.

Mis à jour le 18 septembre 2015 bouye

ZipInputStream
La classe java.util.zip.ZipInputStream permet d’accéder séquentiellement au contenu d'une archive depuis un flux source, par exemple depuis un flux de fichier. Lorsque vous avez fini d'utiliser le flux permettant de lire du contenu au format ZIP, vous devrez invoquer sa méthode close(). Il est possible d'utiliser cette classe avec un try-with-resources :

Code Java : Sélectionner tout
1
2
3
4
try (FileInputStream fileInput = new FileInputStream("monFichier.zip"); 
    ZipInputStream zipInput = new ZipInputStream(fileInput)) { 
    [...] 
}

Ici, l’accès est séquentiel et il faut parcourir toutes les entrées précédentes pour récupérer une entrée donnée.

ZipFile
Vous pouvez également créer une nouvelle instance de la classe java.util.zip.ZipFile en spécifiant comme paramètre le nom d'un fichier ZIP déjà existant. Lorsque vous avez fini d'utiliser le fichier ZIP, vous devrez invoquer sa méthode close(). Il est possible d'utiliser cette classe avec un try-with-resources :

Code Java : Sélectionner tout
1
2
3
try (ZipFile zipFile = new ZipFile("monFichier.zip")) { 
    [...] 
}

La classe ZipFile permet de réaliser des accès aléatoires (ou encore directs) sur le contenu de l'archive. Ceci permet d’accéder au contenu sans ordre particulier ou d’accéder uniquement à un fichier donné de l'archive au lieu de son intégralité. De plus, le fichier de l'archive est mappé en mémoire et donc les accès sont plus rapides qu'avec un ZipInputStream. Par contre cette méthode ne fonctionne qu'avec des fichiers ZIP stockés sur le disque ; il est donc impossible, par exemple, de décompresser au vol le contenu d'un flux ZIP en provenance d'un socket.

Mis à jour le 18 septembre 2015 bouye

ZipInputStream
Lorsque le flux ZIP a été ouvert, vous pouvez parcourir séquentiellement chacune des entrées contenues dans le flux en invoquant la méthode getNextEntry() de la classe java.util.zip.ZipInputStream. Cette méthode retourne la valeur null lorsque toutes les entrées du catalogue de l'archive ont été parcourues.

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
try (FileInputStream fileInput = new FileInputStream("monFichier.zip"); 
        ZipInputStream zipInput = new ZipInputStream(fileInput)) { 
    ZipEntry entry = null; 
    while ((entry = zipInput.getNextEntry()) != null) { 
        // Manipulation de l’entrée. 
        System.out.println(entry.getName()); 
        [...] 
        // Fin du traitement de l’entrée. 
        zipInput.closeEntry(); 
    } 
}

Nous invoquons ensuite la méthode closeEntry() pour indiquer que nous en avons terminé avec cette entrée.

ZipFile
Lorsque le fichier ZIP a été ouvert, vous pouvez récupérer le catalogue des entrées qu'il contient en invoquant la méthode entries() de la classe java.util.zip.ZipEntry. Cette méthode retournera le catalogue des fichiers contenus dans l'archive sous forme d'une Enumeration<? extends ZipEntry>.

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
try (ZipFile zipFile = new ZipFile("monFichier.zip")) { 
    // Récupération du catalogue. 
    Enumeration<? extends ZipEntry> entries = zipFile.entries(); 
    while (entries.hasMoreElements()) { 
        // Récupération d'une entrée du catalogue. 
        ZipEntry entry = entries.nextElement(); 
        // Manipulation de l’entrée. 
        System.out.println(entry.getName()); 
        [...] 
    } 
}

Mis à jour le 18 septembre 2015 bouye

Le traitement des entrées de l'archive permet d'extraire tout ou partie de l'archive vers le système de fichiers.

ZipInputStream
Lorsque le flux ZIP est placé sur une entrée donnée, ce flux permet de lire les données décompressées du fichier référencé par cette entrée.

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ZipInputStream zipInput = [...] 
ZipEntry entry = null; 
while ((entry = zipInput.getNextEntry()) != null) { 
    // Fichier cible. 
    String filename = entry.getName(); 
    Path targetFile = Paths.get(filename); 
    // Si l’entrée référence un répertoire. 
    if (entry.isDirectory()) { 
        Files.createDirectories(targetFile); 
    } else { // Si l’entrée référence un fichier. 
        // S'il faut construire le répertoire parent du fichier. 
        if (targetFile.getParent() != null) { 
            Files.createDirectories(targetFile.getParent()); 
        } 
        // Recopie du contenu du flux vers le fichier cible. 
        Files.copy(input, targetFile); 
    } 
    // Fin du traitement de l’entrée. 
    zipInput.closeEntry(); 
}

ZipFile
Lorsque vous manipulez une entrée d'un fichier ZIP, vous pouvez invoquer la méthode getInputStream() de la classe java.util.zip.ZipFile en lui passant cette entrée comme paramètre. Ce flux permettra de lire les données décompressées du fichier référencé par cette entrée.

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ZipFile zipFile = [...] 
ZipEntry entry = [...] 
try (InputStream input = zipFile.getInputStream(entry)) {    
    // Fichier cible. 
    String filename = entry.getName(); 
    Path targetFile = Paths.get(filename); 
    // Si l’entrée référence un répertoire. 
    if (entry.isDirectory()) { 
        Files.createDirectories(targetFile); 
    } else { // Si l’entrée référence un fichier. 
        // S'il faut construire le répertoire parent du fichier. 
        if (targetFile.getParent() != null) { 
            Files.createDirectories(targetFile.getParent()); 
        } 
        // Recopie du contenu du flux vers le fichier cible. 
        Files.copy(input, targetFile); 
    } 
}

Mis à jour le 18 septembre 2015 bouye

Pour créer une archive au format ZIP, nous allons utiliser la classe java.util.zip.ZipOutputStream. Cette classe permet d’écrire séquentiellement chaque entrée du catalogue de l'archive dans un flux destination, par exemple dans un flux de fichier. Lorsque vous avez fini d'utiliser le flux permettant d'écrire du contenu au format ZIP, vous devrez invoquer sa méthode close(). Il est possible d'utiliser cette classe avec un try-with-resources :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
try (FileOutputStream fileOutput = new FileOutputStream("monFichier.zip"); 
        ZipOutputStream zipOutput = new ZipOutputStream(fileOutput)) { 
    ZipEntry entry = new ZipEntry("bonjour.txt"); 
    zipOutput.putNextEntry(entry); 
    zipOutput.write("Salut le monde !".getBytes("UTF8")); 
    zipOutput.closeEntry(); 
}

Ici, nous avons ouvert un flux permettant de créer une archive ZIP sur le fichier monFichier.zip. Nous créons ensuite une nouvelle entrée nommée "bonjour.txt". Nous positionnons ensuite le flux sur cette entrée en invoquant sa méthode putNextEntry(). Désormais, tout ce que nous écrirons dans le flux avec les méthodes habituelles d’écriture sur des flux sera lié au fichier référencé par l’entrée. Nous invoquons ensuite la méthode closeEntry() pour indiquer que nous en avons terminé avec cette entrée.

Généralement, vous vous contenterez de recopier le contenu d'un fichier déjà présent sur le disque dur plutôt que de générer du contenu au vol.

Code Java : Sélectionner tout
1
2
3
4
5
Path source = [...] 
ZipEntry entry = new ZipEntry(source.getName()); 
zipOutput.putNextEntry(entry); 
Files.coppy(source, zipOutput(); 
zipOutput.closeEntry();

Mis à jour le 18 septembre 2015 bouye

Une archive JAR se lit de la même manière qu'une archive ZIP, mais en utilisant à la place les classes java.util.jar.JarEntry et java.util.jar.JarInputStream ou java.util.jar.JarFile. Cependant une archive JAR peut contenir un fichier manifeste optionnel décrivant l'archive et les types MIME des fichiers inclus, le nom de la classe exécutable, les signatures numériques du contenu, etc. Vous pouvez manipuler le manifeste contenu dans l'archive en invoquant la méthode getManifest() des classes JarInputStream et JarFile. Cette méthode retourne une instance de la classe java.util.jar.Manifest.

JarInputStream

Code Java : Sélectionner tout
1
2
3
4
5
try (FileInputStream fileInput = new FileInputStream("monFichier.jar");  
        JarInputStream jarInput = new JarInputStream(fileInput)) {  
    Manifest manifest = jarFile.getManifest(); 
    [...] 
}

JarFile

Code Java : Sélectionner tout
1
2
3
4
try (JarFile jarFile = new JarFile("monFichier.jar")) {  
    Manifest manifest = jarFile.getManifest(); 
    [...] 
}

Note : dans les deux cas, cette méthode peut retourner la valeur null si l'archive JAR ne contient pas de manifeste.

Mis à jour le 21 septembre 2015 bouye

Une archive JAR se crée de la même manière qu'une archive ZIP, mais en utilisant à la place les classes java.util.jar.JarEntry et java.util.jar.JarOutputStream. Il est possible de spécifier un manifeste préconstruit optionnel lors de la création du flux en fournissant au constructeur, une instance de la classe java.util.jar.Manifest.

Code Java : Sélectionner tout
1
2
3
4
5
6
7
Manifest manifest = new Manifest(); 
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); 
try (FileOutputStream fileOutput = new FileOutputStream("monFichier.jar"); 
    JarOutputStream jarOutput = new JarOutputStream(fileOutput, manifest)) { 
    JarEntry entry = new JarEntry("bonjour.txt"); 
    [...] 
}

Ce faisant, un fichier META-INF/MANIFEST.MF sera rajouté dans l'archive. Ce fichier contient la ligne suivante :

Code Text : Sélectionner tout
Manifest-Version: 1.0

Ce qui correspond à l'attribut Attributes.Name.MANIFEST_VERSION que nous avons utilisé.

Vous trouverez une liste exhaustive des attributs possibles dans la javadoc de la classe java.util.jar.Attributes.Name. Par exemple, l’attribut Attributes.Name.MAIN_CLASS permet de définir le nom de la classe de lancement de l'application lors de la création d'un fichier JAR exécutable.

Mis à jour le 21 septembre 2015 bouye

Vous avez deux manières de rajouter un répertoire dans une archive ZIP ou JAR :

  • n'importe quelle entrée dont le nom se termine par le caractère '/' est considérée comme étant le nom d'un répertoire.

    Code Java : Sélectionner tout
    1
    2
    3
    4
    ZipEntry entry = new ZipEntry("test/"); 
    zipOutput.putNextEntry(entry); 
    // On écrit rien dans le flux. 
    zipOutput.closeEntry();

    Désormais notre archive ZIP ou JAR contient une entrée nommée test/ qui dénote un répertoire vide. Lors de l'extraction de cette entrée, la méthode isDirectory() de la classe java.util.zip.ZipEntry ou java.util.jar.JarEntry retournera la valeur true. Cette manière de faire permet de stocker des répertoires vides dans une archive ;
     
  • n'importe quel répertoire se trouvant dans le nom de chemin d'une entrée (fichier ou autre répertoire) dénote un répertoire existant de manière implicite. C'est-à-dire qu'il n'existe pas d’entrée dans l'archive contenant ce répertoire, mais qu'il peut être recouvré grâce au chemin généré par le nom de l’entrée.

    Code Java : Sélectionner tout
    1
    2
    3
    4
    5
    ZipEntry entry = new ZipEntry("rep1/rep2/fichier.txt"); 
    zipOutput.putNextEntry(entry); 
    // Écriture du fichier dans le flux. 
    [...] 
    zipOutput.closeEntry();

    Ici, nous n'avons pas créé explicitement d’entrées pour le répertoire rep1 et son sous-répertoire rep2 mais leur présence est implicite à cause de l'existence de l’entrée rep1/rep2/fichier.txt. Il faudra donc prendre soin de créer la structure de stockage appropriée lors de l'extraction de l'archive.


Ces deux manières de faire ne sont pas mutuellement exclusives.

Mis à jour le 18 septembre 2015 bouye

Pour compresser une archive JAR en utilisant la méthode de compression Pack200, nous allons utiliser la méthode pack() de la classe java.util.jar.Pack200.Packer. Cette classe compresse un flux d’entrée JAR ou un fichier JAR vers un flux de sortie, par exemple dans un flux de fichier.

JarInputStream

Code Java : Sélectionner tout
1
2
3
4
5
try (FileInputStream fileInput = new FileInputStream("monFichier.jar");  
        JarInputStream jarInput = new JarInputStream (fileInput); 
        OutputStream packOutput = new FileOutputStream("monfichier.pack.gz")) { 
    packer.pack(jarInput, packOutput); 
}

JarFile
Code Java : Sélectionner tout
1
2
3
4
try (JarFile jarFile = new JarFile("monFichier.jar"); 
        OutputStream packOutput = new FileOutputStream("monfichier.pack.gz")) { 
    packer.pack(jarFile, packOutput); 
}

Ici, dans les deux cas, nous recopions le contenu du fichier monFichier.jar en compressant les données avec la méthode de compression Pack200 dans un nouveau fichier nommé monfichier.pack.gz

Mis à jour le 21 septembre 2015 bouye

Pour décompresser une archive JAR utilisant la méthode de décompression Pack200, nous allons utiliser la méthode unpack() de la classe java.util.jar.Pack200.Unpacker. Cette classe décompresse un fichier ou un flux d’entrée au format Pack200 vers un flux de sortie JAR, par exemple dans un flux de fichier.

Code Java : Sélectionner tout
1
2
3
4
5
6
Pack200.Unpacker unpacker = Pack200.newUnpacker(); 
try (InputStream packInput = new FileInputStream("monfichier.pack.gz"); 
        FileOutputStream fileOutput = new FileOutputStream("monFichier.jar"); 
        JarOutputStream jarOutput = new JarOutputStream(fileOutput)) { 
    unpacker.unpack(packInput, jarOutput); 
}

Ici, nous recopions le contenu du fichier monfichier.pack.gz en décompressant les données avec la méthode de décompression Pack200 dans un nouveau fichier JAR nommé monFichier.jar.

Mis à jour le 21 septembre 2015 bouye

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.