Plan du site  
pixel
pixel

Articles - Étudiants SUPINFO

Exemple d'un programme de packaging de fichiers en JAVA

Par Corentin SPORTIELLO Publié le 01/07/2015 à 22:00:07 Noter cet article:
(0 votes)
Avis favorable du comité de lecture

Principe du packaging

Le principe du packaging de multiples fichiers est simple : nous avons plusieurs fichiers, plus ou moins volumineux et de formats différents, et nous voulons les "réunir" dans un seul et même fichier. Ce fichier de sortie est alors le "package" contenant tous nos fichiers , il est similaire à un fichier d'archive . On peut ainsi stocker un grand nombre de fichiers dans un seul fichier de sortie, ce qui permet par exemple d'encrypter ce dernier pour pouvoir protéger tout son contenu .

Enfin , on pourrait comparer ce procédé avec celui d'une compression d'un dossier vers un fichier (zip, rar , tar gz ...), à la différence que notre but dans cet article est uniquement d'archiver, aucune compression n'est donc effectuée sur les données. Notre fichier de sortie aura donc approximativement la même taille que l'ensemble de nos fichiers réunis.

Le but principal de cet aricle est de fournir un exemple concret de l'utilisation des Readers/Writers en JAVA, ainsi qu'un aperçu des interfaces graphiques (GUI) .

Cahier des charges du programme

Dans cet article, nous nous limiterons à l'archivage d'un seul repertoire contenant uniquement des fichiers.

En effet, le but est ici de montrer le fonctionnement de plusieurs objets disponibles dans les bibliothèques JAVA et nous voulons garder un code clair et simple.

Néanmoins, après la lecture de cet article, vous devriez être capable de compléter le programme pour y ajouter la gestion de sous-répertoires (par récursivité, par exemple)

En résumé, notre programme devra être capable de former un seul fichier de sortie qui contiendra les données des fichiers contenus dans un répertoire choisi par l'utilisateur.

Aussi, le choix du répertoire sera effectué à l'aide d'une interface graphique (GUI), cela nous permettra d'aborder des thèmes comme la programmation événementielle et les interfaces graphiques en JAVA

Avant de commencer

Tout au long de cet article , nous utiliserons l'IDE Eclipse pour JAVA disponible ici : https://eclipse.org/downloads/

Il nous faudra aussi un JRE JAVA installé sur notre ordinateur (probablement déjà installé sur votre système), disponible ici : https://java.com/download

Avant de commencer à coder, nous allons créer un projet avec son arborescence .

Demarrez Eclipse puis choisissez l'emplacement de votre workspace (vous pouvez aussi laisser celui par défaut) .

Créez alors un nouveau projet en cliquant sur File -> New -> Java Project . Choisissez alors un nom pour votre projet dans la fenêtre qui vient d'apparaître . Pour notre part, nous nommerons notre projet "FilePackaging"

Un projet est alors créé dans l'arborescence disponible sur la gauche d' Eclipse.

Cliquez droit sur "src" situé sous le repertoire de votre projet , puis "New" -> "Package" et choisissez un nom pour votre package.

Dans notre exemple "com.supinfo.articles.packaging". Voici à quoi devrait ressembler l'arborescence de votre projet :

Enfin, nous créérons ici deux classes, "MainFrame" et "ChooseListener" qui contiendront respectivement notre interface graphique et le listener d'un bouton qui nous permettra par la suite de choisir le répertoire à archiver.

Pour cela , faites clic droit sur votre package précédemment créé, puis "New" -> "Class" et choisissez un nom dans le champ "Name" puis appuyez sur Entrée . Nous sommes enfin prêts à commencer .

L' interface graphique : MainFrame.java

Rendez vous dans la classe MainFrame , vous devriez avoir le code suivant déjà présent:

package com.supinfo.articles.packaging;

public class MainFrame {

}

Nous allons ici faire hériter notre classe de JFrame pour en faire une fenêtre et écrire son constructeur pour afficher une fenêtre de base. Nous ajouterons aussi la methode main (point d'entrée du programme) dans cette même classe :

public class MainFrame extends JFrame {

  private static final long serialVersionUID = 1L //(Facultatif ici, utilisé pour la serialisation)

  public MainFrame()
  {
      super("File Packaging");
      this.setSize(new Dimension(800,150)); //Dimensions fenêtre
      this.setLocationRelativeTo(null); //Centrage à l'ecran
      this.setVisible(true); //On affiche la fenêtre
      this.setDefaultCloseOperation(EXIT_ON_CLOSE); //On définit la fermeture du programme sur la croix rouge
  }

  public static void main(String [] args)
  {
      new MainFrame();
  }

}

Sauvegardez (Raccourci : Ctrl +S) et lancez l'application avec le bouton indiqué ci dessous:

Vous pouvez alors voir apparaître une fenêtre vide qui est la base de notre interface graphique :

Nous allons ensuite ajouter les composants suivants à notre interface :

  • Un JTextField (champ de texte) qui contiendra le chemin de notre répertoire contenant les fichiers à archiver

  • Un JButton (bouton) qui nous servira à rechercher un répertoire sur notre système

  • Un autre JButton pour lancer l'archivage .

Comme le but de cet article n'est pas d'apprendre à créer une interface graphique en JAVA , nous nous contenterons de vous présenter le code pour ajouter ces composants précédents .

Nous créons d'abord les differents champs qui contiendront nos composants de la liste précédente :

private JPanel _contentPane;
private JTextField _pathField;
private JButton _choseFolder;
private JButton _startButton ;

Nous ajoutons ensuite la méthode buildGUIComponents , qui va se charger comme son nom l'indique de créer les composants de notre interface et de les ajouter dans notre fenêtre :

private void buildGUIComponents()
{
  this.setSize(new Dimension(800,150));
  _contentPane = new JPanel(new BorderLayout());
  _pathField = new JTextField(20);
  _choseFolder = new JButton("Browse ...");	
  
  //Sub panel contenant le choix du dossier
  JPanel choicePanel = new JPanel();
  choicePanel.setBorder(BorderFactory.createTitledBorder("Folder choice "));
  choicePanel.add(_pathField);
  choicePanel.add(_choseFolder);
  
  
  _startButton = new JButton("Start");
  
  //Sub panel contenant la progression et le bouton de démarrage
  JPanel southPanel = new JPanel();
  southPanel.add(_startButton);
  
  //Ajout des subPanels dans le  content pane
  _contentPane.add(choicePanel,BorderLayout.CENTER);
  _contentPane.add(southPanel, BorderLayout.SOUTH);
  
  
  
  this.setContentPane(_contentPane);

}

Enfin nous appelons la méthode buildGUIComponents dans le constructeur, juste après l'instruction "this.setSize(...);" :

public MainFrame()
{
  super("File packaging");
  this.setSize(new Dimension(800,150)); //Dimensions de la fenêtre
  
  buildGUIComponents();  //Construction des composants de l'interface
  
  this.setLocationRelativeTo(null); //Centrage à l'ecran
  this.setVisible(true); //On affiche la fenêtre
  this.setDefaultCloseOperation(EXIT_ON_CLOSE); //On définit la fermeture du programme sur la croix rouge
}

Le code de la classe MainFrame devrait ressembler à cela :

package com.supinfo.articles.packaging;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class MainFrame extends JFrame
{
  private static final long serialVersionUID = 1L; //Utile en cas de sérialisation de cet objet
  
  private JPanel _contentPane;
  private JTextField _pathField;
  private JButton _choseFolder;
  private JButton _startButton ;
 
 
  public MainFrame()
  {
    super("File packaging");
    this.setSize(new Dimension(800,150)); //Dimensions de la fenêtre
    
    buildGUIComponents();
    
    this.setLocationRelativeTo(null); //Centrage à l'ecran
    this.setVisible(true); //On affiche la fenêtre
    this.setDefaultCloseOperation(EXIT_ON_CLOSE); //On définit la fermeture du programme sur la croix rouge
  }
  
  /**
   * Methode de construction graphique de la fenêtre et de ses composants
   */
  private void buildGUIComponents()
  {
    this.setSize(new Dimension(800,150));
    _contentPane = new JPanel(new BorderLayout());
    _pathField = new JTextField(20);
    _choseFolder = new JButton("Browse ...");	
    
    //Sub panel contenant le choix du dossier
    JPanel choicePanel = new JPanel();
    choicePanel.setBorder(BorderFactory.createTitledBorder("Folder choice "));
    choicePanel.add(_pathField);
    choicePanel.add(_choseFolder);
    
    
    _startButton = new JButton("Start");
   
    //Sub panel contenant la progression et le bouton de démarrage
    JPanel southPanel = new JPanel();
    southPanel.add(_startButton);
    
    //Ajout des subPanels dans le  content pane
    _contentPane.add(choicePanel,BorderLayout.CENTER);
    _contentPane.add(southPanel, BorderLayout.SOUTH);



    this.setContentPane(_contentPane);

  }
  
  public static void main(String [] args)
  {
    new MainFrame();
  }

}

Lancez alors l'application , vous devriez obtenir une fenêtre semblable à celle ci :

Notez que vous pouvez modifier à votre guise le code pour avoir une interface qui vous convient mieux, le but étant ici d'avoir nos composants principaux qui sont les deux JButton et le JTextField .

Un peu de programmation évenementielle : Ajout de listeners

Notre interface graphique est créée certes, mais pour le moment il n'y a aucun moyen pour l'utilisateur d'effectuer des actions sur celle-ci !

En effet, il va falloir récupérer les entrées utilisateurs (clics sur les boutons Browse et Start) pour permettre à l'utilisateur d'interagir avec notre programme.

Cela tombe bien, il y a des interfaces justement prévues pour ça : les listeners .

Pour ajouter un Listener sur un bouton , c'est assez simple, il suffit d'appeler la méthode addActionListener(ActionListener listener) de notre JButton :

 myButton.addActionListener(ActionListener listener);

Cette méthode peut prendre en paramètre n'importe quel objet, à partir du moment ou ce dernier implémente l'interface ActionListener.java .

Dirigez vous alors dans la classe ChooseListener.java et laissez cette dernière implémenter l'interface ActionListener :

public class ChooseListener implements ActionListener {

Eclipse vous indiquera une erreur , vous demandant d'importer la classe ActionListener, puis une fois importé, une autre erreur apparaîtra vous indiquant que certaines méthodes de l'interface ActionListener ne sont pas implémentées , cliquez alors sur l'erreur et corrigez là en cliquant sur la proposition "add unimplemented methods" pour corriger ce problème.

Une méthode s'ajoute alors dans votre éditeur :

@Override
  public void actionPerformed(ActionEvent e) 
  {
    // TODO Auto-generated method stub
  }

C'est en fait la méthode qui va être appelée lors du clic sur le bouton auquel on aura spécifié ce listener.

C'est alors à nous de gérer l'evenement comme on le souhaite à l'interieur de cette méthode.

Pour rappel, notre objet ChooseListener , qui implémente maintenant ActionListener, doit permettre de choisir un répertoire sur notre système , et écrire son chemin absolu dans le JTextField de notre interface.

Cependant nous n'avons pas accès au JTextField directement depuis le listener ! Pour cela écrivons le constructeur de notre objet ChooseListener , de sorte à prendre le JTextField dans lequel on va écrire en paramètre, puis on stockera cet objet dans un attribut de ChooseListener que l'on nommera ici "_textField " .

On écrit alors le champ dans la classe ChooseListener :

private JTextField _textField;

Puis on écrit ensuite son constructeur :

  public ChooseListener(JTextField param)
  {
    this._textField = param;
  }

Ainsi nous pourrons interagir avec ce JTextField que l'on aura récupéré lors de la construction de notre objet ChooseListener .

Retournons alors dans la classe MainFrame.java , et ajoutons à la fin de la méthode buildGUIComponents la ligne suivante :

_choseFolder.addActionListener(new ChooseListener(this._pathField));

Cette instruction nous permet d'ajouter un listener au bouton _choseFolder (notre bouton "Browse") , qui est en fait un objet ChooseListener .

On instancie ce ChooseListener en passant en paramètre de notre constructeur le JTextField _pathField qui contiendra le chemin du dossier à archiver.

Maintenant que nous avons "lié" notre bouton _choseFolder à un ChooseListener, il ne nous reste plus qu' à gérer l'evenement du clic souris en modifiant la méthode actionPerformed de notre listener .

Retournons alors dans la classe ChooseListener.java et modifions la méthode actionPerformed ainsi :

 /**
   * Choix d'un repertoire à archiver via un JFileChooser.
   */
  @Override
  public void actionPerformed(ActionEvent e) 
  {
    JFileChooser chooser = new JFileChooser();
    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);   
    int returnVal = chooser.showOpenDialog(null);
    if(returnVal == JFileChooser.APPROVE_OPTION) 
    {
         File folder = chooser.getSelectedFile();
         this._textField.setText(folder.getAbsolutePath());
    }
  }

Ce que fait cette méthode est assez simple :

On instancie un JFileChooser qui est un objet de la bibliothèque javax.swing qui nous permet de rechercher un fichier/dossier sur le système grâce à une boîte de dialogue.

on utilise setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); pour spécifier au JFileChooser que l'on ne peut choisir que des dossiers.

Les instructions qui suivent permettent de récuperer le dossier selectionné lorsque l'utilisateur appuie sur "Ok" dans le JFileChooser , et d'ecrire dans notre JTextField le chemin absolu du fichier grâce à l'instruction this._textField.setText(folder.getAbsolutePath()); .

Sauvegardez et lancez à nouveau le programme , cliquez alors sur le bouton "Browse" de l'interface. Le JFileChooser vous demander alors de choisir un dossier :

Choisissez un repertoire puis cliquez sur "Ouvrir", la fenêtre disparait alors, et vous pouvez voir écrit le chemin de votre dossier dans le JTextField de notre interface graphique.

Bien, nous avons presque fini pour l'interface . Il nous reste à ajouter un listener pour le bouton start. Nous ne détaillerons pas ici le code puisque c'est le même principe que pour le bouton Browse.

Sachez cependant qu'il vous faudra créer une nouvelle classe dans votre projet pour le Listener du bouton start. Nous l'apellerons pour notre part StartListener.java , voici son contenu :

package com.supinfo.articles.packaging;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JTextField;

public class StartListener implements ActionListener{

  private JTextField _textField;
  
  public StartListener(JTextField param)
  {
    _textField = param;
  }
  
  @Override
  public void actionPerformed(ActionEvent e)
  {
    File f = new File(this._textField.getText()); // on récupere le fichier au chemin absolu du textfield
    if(f.exists() && f.isDirectory())
    {
      this.packDirectory(f);
    }
  }
  
  private void packDirectory(File directory)
  {
    //On se chargera ici de créer l'archive
  }

}

La structure de cette classe est sensiblement la même que pour la classe FileChooser.java , nous récuperons là aussi le JTextField dans le constructeur pour s'en servir dans la méthode actionPerformed .

Dans cette dernière méthode nous récupérons le fichier correspondant au chemin contenu dans le JTextField en instanciant un objet File puis en vérifiant que ce dernier existe et que c'est bel et bien un dossier.

Si c'est le cas, nous apellons alors la méthode privée packDirectory(File directory) pour procéder à l'archivage de notre dossier.

Enfin , retournez dans la classe MainFrame et ajoutez ceci à la fin de la méthode buildGUIComponents pour lier notre listener au bouton "Start" :

_startButton.addActionListener(new StartListener(this._pathField));

Rendez vous maintenant à la prochaine étape : modifier la méthode packDirectory pour pouvoir (enfin) archiver le contenu de notre dossier !

Let's pack !

Enfin, nous voici dans la dernière ligne droite : nous avons récupéré le dossier choisi par l'utilisateur, il ne nous manque plus qu' à archiver les fichiers qu'il contient !

Cette partie va nous permettre de voir un exemple d'utilisation de quelques objets interessants de la bibliothèque java.IO pour ecrire et lire dans des fichiers.

Le format d'ecriture

Tout d'abord , il faut réfléchir à la façon dont on va ecrire le contenu de chaque fichier à la suite dans le fichier de destination.

Avant d' écrire les données de chaque fichier dans le fichier de destination (archive) il nous faut d'abord certaines informations:

  • Le nombre de fichiers à archiver

  • Le nom de chaque fichier

  • La taille de chaque fichier

  • Les données de chaque fichier

Pour cela nous devons alors lister les fichiers du répertoire dans un tableau, récuperer la taille du tableau pour avoir le nombre de fichiers.

Ensuite nous parcourons avec une boucle tous les éléments du tableau, et nous récupérons leur nom,taille,et leur données (en lisant le fichier)

Une fois que l'on a toutes ces données le schéma d'écriture est le suivant :

Au début du fichier on ecrit un int qui contient le nombre de fichiers stockés dans l'archive .

Ensuite tous les fichiers sont écrit à la suite sous ce format : nom du fichier sous forme de string , suivi de sa taille au format long , et enfin tous les octets (byte) du contenu du fichier

L'algorithme

Voici la méthode packDirectory , une fois totalement modifiée pour pouvoir "packer" les fichiers de notre dossier choisi .

private void packDirectory(File directory)
  {
    //On crée un nouveau fichier de sortie
    String outputPath = directory.getAbsolutePath().substring(0,directory.getAbsolutePath().lastIndexOf("\\")+1)+directory.getName().replaceAll(" ", "_")+".szip";
    File out = new File(outputPath);
    if(!out.exists())
    {
      try {
        out.createNewFile(); // On essaye de créer le fichier de sortie s'il n'existe pas.
      } catch (IOException e) {
        System.out.println("Impossible de créer le fichier de sortie !");
        return;
      } 
    }
    
    //On initialise notre Writer et notre Reader à null
    DataOutputStream writer = null;
    DataInputStream reader = null;
    
    try{
      writer = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(out)));
      
      //On recupere les fichiers du dossier à archiver
      File[] toPack = directory.listFiles(); 
      
      //On compte le nombre de fichiers uniquement
      int fileCount = 0;
      for(int i = 0 ; i < toPack.length ; i ++)
      {
        if(toPack[i].isFile())
        {
          fileCount ++;
        }
      }
      writer.writeInt(fileCount); // on l'ecrit au début du fichier de sortie.
      
      //Ensuite on parcours chaque fichier à ecrire
      for(File f : toPack)
      {
        if(f.isFile())
        {
          //On recupere le nom + la longueur du fichier
          String name = f.getName();
          long length = f.length();
          
          //On ecrit alors ces informations
          writer.writeUTF(name);
          writer.writeLong(length);
          
          //Puis on copie le contenu du fichier à la suite
          reader = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
          final byte[] buffer = new byte[1024]; //tampon 
          int dataCount;
          while((dataCount = reader.read(buffer, 0, buffer.length)) != -1 )
          {
            writer.write(buffer, 0, dataCount);
          }
          //On ferme le flux de lecture.
          reader.close();
        }  
      }//Fin de parcours des fichiers
      
    }catch(IOException e){
      System.out.println("Erreur lors de l'archivage du fichier : ");
      e.printStackTrace();
    }
    finally
    {
      try {
        if(writer != null)
        {
          writer.flush();
          writer.close();
        }
        if(reader != null)
        {
          reader.close();
        }
        
      } catch (IOException e) {
        System.out.println("Impossible de fermer correctement les flux ");
      }
      
    }
        
  }

Nous allons expliquer au fur et à mesure cette méthode qui peut paraître au premier abord complexe, mais qui n'est finallement que la traduction de ce que l'on a ennoncé plus tôt.

Tout d'abord :

//On crée un nouveau fichier de sortie
    String outputPath = directory.getAbsolutePath().substring(0,directory.getAbsolutePath().lastIndexOf("\\")+1)+directory.getName().replaceAll(" ", "_")+".szip";
    File out = new File(outputPath);
    if(!out.exists())
    {
      try {
        out.createNewFile(); // On essaye de créer le fichier de sortie s'il n'existe pas.
      } catch (IOException e) {
        System.out.println("Impossible de créer le fichier de sortie !");
        return;
      } 
    }

Ces lignes nous permettent de créer le fichier de sortie (extension .szip , pour "Supzip" ) .

La string outputPath est le chemin du fichier de sortie , que l'on recupere en prenant le chemin du répertoire parent du répértoire passé en paramètre + le nom du dossier que l'on veut archiver + l'extension ".szip"

Ensuite on instancie l'objet File correspondant au fichier de sortie, et , si celui-ci n'existe pas déjà, on le créé .

Après nous avons deux lignes intéréssantes :

//On initialise notre Writer et notre Reader à null
    DataOutputStream writer = null;
    DataInputStream reader = null;

Ce sont en fait nos deux objets qui vont nous permettre de lire et écrire des données .

Nous les initialisons à null en dehors de la clause try qui suit pour que nous puissions y accéder dans la clause "finally" qui nous permettra de fermer proprement les flux.

Les instructions qui suivent peuvent lever des exceptions de type IOException , c'est pour cela qu'elles sont situés à l'interieur du "try catch"

writer = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(out)));

Cette instruction nous permet d'instancier notre writer , en passant par un tampon d'ecriture puis enfin dans le flux d'ecriture du fichier. L'utilisation d'un BufferedOutputStream en tampon nous permet ici de gagner du temps d'execution lors de l'ecriture de fichiers volumineux.

 //On recupere les fichiers du dossier à archiver
      File[] toPack = directory.listFiles(); 
      
      //On compte le nombre de fichiers uniquement
      int fileCount = 0;
      for(int i = 0 ; i < toPack.length ; i ++)
      {
        if(toPack[i].isFile())
        {
          fileCount ++;
        }
      }
      writer.writeInt(fileCount); // on l'ecrit au début du fichier de sortie.

Ici, conformément à notre format d' écriture cité dans la partie précédente, nous listons les fichiers du dossier avec l'instruction listFiles() qui nous renvoie le tableau des fichiers

( qu'ils soient des fichiers ou dossiers) situés dans le répertoire .

Ensuite on parcours ce tableau pour ne compter que les fichiers (donc on exclut les dossiers) .

On écrit enfin la valeur de fileCount au début de notre fichier de sortie .

 //Ensuite on parcours chaque fichier à ecrire
      for(File f : toPack)
      {
        if(f.isFile())
        {
          //On recupere le nom + la longueur du fichier
          String name = f.getName();
          long length = f.length();
          
          //On ecrit alors ces informations
          writer.writeUTF(name);
          writer.writeLong(length);
          
          //Puis on copie le contenu du fichier à la suite
          reader = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
          final byte[] buffer = new byte[1024]; //tampon 
          int dataCount;
          while((dataCount = reader.read(buffer, 0, buffer.length)) != -1 )
          {
            writer.write(buffer, 0, dataCount);
          }
          //On ferme le flux de lecture.
          reader.close();
        }  
      }//Fin de parcours des fichiers

Voici ici la partie d'ecriture qui va se conformer à notre schéma qui était pour rappel : nomdefichier + taillefichier + contenudufichier

On ecrit le nom et la taille comme ceci , ce qui est assez explicite :

          String name = f.getName();
          long length = f.length();
          
          //On ecrit alors ces informations
          writer.writeUTF(name);
          writer.writeLong(length);

Ensuite on va copier/coller le contenu du fichier dans l'archive , il s'agit en fait de lire le fichier source par tranche de 1024 octets (1ko) et de l'ecrire dans le fichier de destination

//Puis on copie le contenu du fichier à la suite
          reader = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
          final byte[] buffer = new byte[1024]; //tampon 
          int dataCount;
          while((dataCount = reader.read(buffer, 0, buffer.length)) != -1 )
          {
            writer.write(buffer, 0, dataCount);
          }

La méthode read comporte 3 paramètres :

  • le buffer , un tableau d'octets (byte[]) dans lequel on va stocker ce qu'on lit

  • un int qui correspond à l'offset qui indique l'index ou l'on va commencer à stocker les données dans le buffer

  • un int qui indique combien d'octets on doit lire.

La méthode retourne un int correspondant au nombre d'octets lus , ou la valeur -1 si on est arrivé à la fin du fichier .

La méthode write est basée sur le même principe pour les paramètres :

  • le buffer , un tableau d'octets (byte[]) comprenant les octets à ecrire

  • un int qui correspond à l'offset qui indique l'index à partir du quel on écrit les données du buffer

  • un int qui indique combien d'octets on doit écrire.

Enfin dans le reste de la méthode, on ferme les flux le plus proprement possible :

finally
    {
      try {
        if(writer != null)
        {
          writer.flush();
          writer.close();
        }
        if(reader != null)
        {
          reader.close();
        }
        
      } catch (IOException e) {
        System.out.println("Impossible de fermer correctement les flux ");
      }
      
    }

Notre programme est désormais fini !

Sauvegardez puis lancez à nouveau le programme, selectionnez un dossier dont vous voulez "packer" les fichiers ( par exemple un dossier de playlist contenant toutes vos musiques)

Appuyez sur le bouton start , et vous verrez apparaître le fichier d'archive au format .szip dans le même répertoire que le dossier ciblé .

Vous avez réussi à faire votre premier package de dossiers !

Comment "unpack" notre fichier .szip

Maintenant que nous avons notre fichier .szip , nous aimerions utiliser un procédé inverse afin de le retransformer en dossier contenant tous nos fichiers.

Nous ne détaillerons pas comment expliquer ce procédé dans cet article car le but était essentiellement d'avoir quelques aperçus sur l'ecriture et la lecture de données (binaires) dans des fichiers, ainsi que de voir quelques notions sur les interfaces graphiques avec notamment les objets de la bibliothèque javax.swing

Sachez néanmoins que réaliser ce procédé inverse est totallement réalisable, pour preuve voici les sources du projet pour l'unpacking des données :

https://github.com/Cocow51/FileUnpacker/tree/master

Voici le jar éxécutable si vous desirez tester l'unpacking sur un fichier .szip : http://ge.tt/8a8ImWJ2/v/0

Vous remarquerez que nous avons effectué quelques modifications mais que le principe reste le même que pour ce projet.

Vous êtes libres de réutiliser ces sources dans vos projets futurs.

Pour aller plus loin

Nous avons réalisé ici un système d'archivage très simple, avec peu de fonctionnalités .

Il y a maintenant plein de choses que nous pourrions faire à partir de ce projet , voici quelques exemples possibles :

  • Utiliser un algorithme de compression pour créer des dossiers compréssés

  • Implémenter la gestion des sous dossiers (en utilisant des méthodes récursives , c'est tout à fait possible)

  • Encrypter les données du fichier (mot de passe ou autre etc...)

  • Regrouper les fonctions de compression/décompression dans la même interface graphique

  • Ajouter une barre de progression pour les fichiers volumineux (voir du coté de l'objet JProgressBar en JAVA)

Et il y a encore pleins d'autres possibilités pour compléter cette application !

Conclusion

Merci à vous pour avoir lu cet article jusqu'au bout!

J'espere pour ma part vous avoir appris pas mal de choses à propos du développement en JAVA, en abordant notamment quelques concepts simples comme les GUI, les Listeners , mais surtout l'ecriture et la lecture de fichiers, à travers un exemple concret , qui peut rappeler l'usage de certains logiciels d'archivage/compression de fichiers tels que WinRar, 7Zip etc...

Libre à vous d'appliquer ce que vous avez appris pour effectuer du traitement de fichiers ou encore développer d'autres programmes à interface graphique en JAVA .

Annexe

Voici les sources du projet :

https://github.com/Cocow51/FilePacker

Ainsi que l'executable :

http://ge.tt/572UqWJ2/v/0

Vous êtes libre de réutiliser ces sources comme bon vous semble dans vos projets futurs.

A propos de SUPINFO | Contacts & adresses | Enseigner à SUPINFO | Presse | Conditions d'utilisation & Copyright | Respect de la vie privée | Investir
Logo de la société Cisco, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société IBM, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sun-Oracle, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Apple, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sybase, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Novell, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Intel, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Accenture, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société SAP, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Prometric, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Toeic, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo du IT Academy Program par Microsoft, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management

SUPINFO International University
Ecole d'Informatique - IT School
École Supérieure d'Informatique de Paris, leader en France
La Grande Ecole de l'informatique, du numérique et du management
Fondée en 1965, reconnue par l'État. Titre Bac+5 certifié au niveau I.
SUPINFO International University is globally operated by EDUCINVEST Belgium - Avenue Louise, 534 - 1050 Brussels