begin process at 2012 02 14 05:09:01
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Application

 > LECTURE ET ÉCRITURE DE FICHIERS SCL (SUPERCOPIER LIST)

LECTURE ET ÉCRITURE DE FICHIERS SCL (SUPERCOPIER LIST)


 Information sur la source

Note :
Aucune note
Catégorie :Application Classé sous :supercopier, scl, super, copier Niveau :Débutant Date de création :07/09/2010 Date de mise à jour :07/09/2010 21:53:05 Vu / téléchargé :2 556 / 106

Auteur : nulloz

Ecrire un message privé
Commentaire sur cette source (0)
Ajouter un commentaire et/ou une note

 Description

Ce code permet de lire et d'écrire des fichiers SCL qui sont les fichiers utilisés avec le programme SuperCopier.

Source

  • package scl;
  • import java.util.Arrays;
  • import java.util.HashMap;
  • import java.util.Map;
  • import java.util.Map.Entry;
  • import java.util.Vector;
  • /**
  • * Permet de lire et de créer des fichiers .SCL (SuperCopier List) en version 1.
  • *
  • * Voici les spécifications de l'encodage du fichier :
  • * - Un fichier SCL est un fichier binaire.
  • * - Les valeurs numériques int et int64 sont encodées en little-endian.
  • * - Les chaînes de caractères sont encodés sous la forme : CHAR1 0x00 CHAR2 0x00 CHAR3 0x00 ...,
  • * Il est donc primordial de connaître la longueur de la chaîne avant de la lire. Cette longueur précède donc à chaque fois une chaîne.
  • * Cependant, cette longueur donne le nombre de caractère d'une chaîne. EX: test = longueur 4. Etant donné que chaque caractère utilise 2 octets (le caractère et 0x00), on doit doubler la longueur pour obtenir le nombre d'octets à lire.
  • * - Le fichier SCL peut-être décomposé en trois parties logiques : l'en-tête, la partie des dossiers et la partie des fichiers.
  • *
  • * La partie en-tête :
  • * --------------------
  • * Les 16 premiers octets sont la signature (magic paquet) permettant de confirmer que l'on traite bien un fichier SCL.
  • * Les 4 octets suivants donnent le numéro de version du fichier SCL.
  • *
  • * La partie dossiers :
  • * --------------------
  • * Chaque bloc d'informations donne 3 valeurs : un id, un dossier source et un dossier destination.
  • *
  • * Cette partie commence par la version de la partie dossiers sur 4 octets. S'en suit directement le nombre de blocs présents, toujours sur 4 octets.
  • *
  • * A la suite de cela sont directement les blocs. Chaque bloc est donc constitué de trois informations :
  • * - l'id est codé sur les 4 premiers octets. Cette ID peut tout simplement être ignoré car, à la suite d'un bug dans le logiciel SuperCopier, la valeur sera toujours 0xff 0xff 0xff 0xff
  • * - les 4 octets suivants donne la taille de la chaîne représentant le répertoire source
  • * - les [longueur * 2] octets suivants représentent la chaîne de caractère du répretoire source
  • * - les 4 octets suivants donne la taille de la chaîne représentant le répertoire de destination
  • * - les [longueur * 2] octets suivants représentent la chaîne de caractère du répertoire de destination
  • *
  • * Ces blocs d'informations sont importants les fichiers sont liés à ceux-ci. Chaque fichier possède un ID qui donne le bloc d'informations auquel il est lié.
  • * Les blocs d'informations des dossiers sont donnés dans l'ordre inverse de leur ID. Par ex: le dernier bloc doit avoir l'ID 0, le bloc précédent l'ID 1, ... le dernier bloc l'ID [NB_BLOCS-1].
  • *
  • * La partie fichiers :
  • * ---------------------
  • * Chaque bloc d'informations donne 3 valeurs : l'id du bloc d'informations de la partie "dossiers" auquel le fichier est lié, le nom du fichier source, le nom du fichier destination et la taille du fichier.
  • *
  • * Cette partie commence par la version de la partie dossiers sur 4 octets. S'en suit directement le nombre de blocs présents, toujours sur 4 octets.
  • *
  • * A la suite de cela sont directement les blocs. Chaque bloc est donc constitué de trois informations :
  • * - l'id du bloc d'informations des dossiers est codé sur 4 octets.
  • * - les 4 octets suivants donne la taille de la chaîne représentant le nom du fichier source
  • * - les [longueur * 2] octets suivants représentent la chaîne de caractère de nom du fichier source
  • * - les 4 octets suivants donne la taille de la chaîne représentant le nom du fichier de destination
  • * - les [longueur * 2] octets suivants représentent la chaîne de caractère du nom du fichier de destination
  • * - les 8 octets suivants donne la taille du fichier
  • */
  • public class SuperCopierList
  • {
  • /**
  • * La signature d'en-ête d'un fichier SCL
  • */
  • private static final byte[] SCL_SIGNATURE = new byte[] { 0x53, 0x43, 0x32, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x20, 0x20, 0x20 };
  • /**
  • * La version du fichier SCL
  • */
  • private static final int COPIER_DATA_VERSION = 1;
  • /**
  • * La version de la partie dossiers du fichier SCL
  • */
  • private static final int DIRLIST_DATA_VERSION = 1;
  • /**
  • * La version de la partie fichiers du fichier SCL
  • */
  • private static final int FILELIST_DATA_VERSION = 1;
  • /**
  • * Lit le contenu d'un fichier SCL et extrait une liste d'éléments.
  • *
  • * Si le fichier est mal formaté, rien n'est p
  • *
  • * @param fileName le chemin complet vers le fichier SCL à ouvrir
  • * @return la lite des fichiers
  • * @throws IllegalArgumentException s'il le fichier n'est pas un SCL, s'il s'agit d'une version non supporté ou que le fichier est corrompu
  • */
  • public static Vector<SuperCopierListItem> read(String fileName)
  • {
  • try {
  • //on récupère les données du fichier
  • byte[] data = Tools.readStream(fileName);
  • //on contrôle la signature d'en-tête
  • if(!checkSignature(data))
  • throw new IllegalArgumentException("Incorrect file's signature");
  • int offset = SCL_SIGNATURE.length;
  • //on contrôle la version du fichier SCL et la version de la partie dossiers
  • if(readInt(data, offset) != COPIER_DATA_VERSION || readInt(data, offset+4) != DIRLIST_DATA_VERSION)
  • throw new IllegalArgumentException("Version not supported");
  • //on extrait le nombre de blocs d'informations des dossiers
  • offset += 8;
  • int countDirs = readInt(data, offset);
  • offset += 4;
  • //on parcourt les blocs d'informations des dossiers
  • String[][] dirs = new String[countDirs][2];
  • for(int i=0; i < countDirs; i++)
  • {
  • //les valeurs sont lus par la fin (dernier element lu doit avoir l'index 0 et le premier countDirs-1)
  • int index = countDirs-1-i;
  • //l'id du dossier, doit être ignoré
  • int idDir = readInt(data, offset);
  • offset += 4;
  • //la longueur de la chaîne du dossier source
  • int lenghtDir1 = readInt(data, offset);
  • offset += 4;
  • //la chaîne du dossier source
  • dirs[index][0] = readString(data, offset, lenghtDir1);
  • offset += (lenghtDir1 * 2);
  • //la longueur de la chaîne du dossier de destination
  • int lenghtDir2 = readInt(data, offset);
  • offset += 4;
  • //la chaîne du dossier de destination
  • dirs[index][1] = readString(data, offset, lenghtDir2);
  • offset += (lenghtDir2 * 2);
  • }
  • //on contrôle la version de la partie fichiers
  • if(readInt(data, offset) != FILELIST_DATA_VERSION)
  • throw new IllegalArgumentException("Version not supported");
  • //on extrait le nombre de blocs d'informations des fichiers
  • offset += 4;
  • int countFiles = readInt(data, offset);
  • offset += 4;
  • Vector<SuperCopierListItem> items = new Vector<SuperCopierListItem>();
  • //on parcout les blocs d'informations des fichiers
  • for(int i=0; i < countFiles; i++)
  • {
  • //l'id du bloc d'informations des dossiers à lier
  • int idDir = readInt(data, offset);
  • offset += 4;
  • //la longueur de la chaîne du nom de fichier source
  • int lenghtDir1 = readInt(data, offset);
  • offset += 4;
  • //la chaîne du nom de fichier source
  • String fileSrc = readString(data, offset, lenghtDir1);
  • offset += (lenghtDir1 * 2);
  • //la longueur de la chaîne du nom de fichier de destination
  • int lenghtDir2 = readInt(data, offset);
  • offset += 4;
  • //la chaîne du nom de fichier de destination
  • String fileDst = readString(data, offset, lenghtDir2);
  • offset += (lenghtDir2 * 2);
  • //la longueur du fichier
  • long fileSize = readInt64(data, offset);
  • offset += 8;
  • //on ajoute l'élément
  • items.add(new SuperCopierListItem(dirs[idDir][0], dirs[idDir][1], fileSrc, fileDst, fileSize));
  • }
  • return items;
  • } catch(ArrayIndexOutOfBoundsException e) { //s'il on lit trop loin c'est que le fichier est corrompu ou incomplet
  • throw new IllegalArgumentException("File's corrupted");
  • }
  • }
  • public static void write(Vector<SuperCopierListItem> items, String fileName)
  • {
  • //--- en-tête ---
  • byte[] data = writeSignature();
  • data = writeInt(data, COPIER_DATA_VERSION);
  • //--- la partie dossier ---
  • Map<String, Object[]> dirs = new HashMap<String, Object[]>(); //on utilise un HashMap pour accélerer la recherche
  • Object[][] dirsRef = new Object[items.size()][3]; //on utilise ce tableau pour référencer les blocs d'informations par rapport à l'ID donné au bloc
  • int index = 0;
  • for(SuperCopierListItem item : items)
  • {
  • String key = item.getDirSrc() + "|" + item.getDirDest();
  • if(!dirs.containsKey(key)) //si on ne trouve pas de correspondance, ce tuple d'informations de dossiers n'existe pas encore
  • {
  • Object[] blocDatas = new Object[] { item.getDirSrc(), item.getDirDest(), index};
  • dirsRef[index] = blocDatas; //on place la référence dans le tableau
  • dirs.put(key, blocDatas); //on créé le bloc d'informations en lui associant un ID pour faire le lien avec les fichiers
  • index++;
  • }
  • }
  • //on écrit la version de la partie dossier
  • data = writeInt(data, DIRLIST_DATA_VERSION);
  • //on écrit le nombre de blocs d'informations
  • data = writeInt(data, dirs.size());
  • //on écrit les blocs d'informations dans l'ordre inverse
  • for(int i=index-1; i >= 0; i--)
  • {
  • //on écrit l'ID du bloc à 0xff 0xff 0xff 0xff (à la suite d'un bug dans SuperCopier)
  • data = writeInt(data, -1);
  • //on écrit la chaîne du dossier source (avec sa longueur juste avant)
  • data = writeString(data, (String)dirsRef[i][0]);
  • //on écrit la chaîne du dossier de destination (avec sa longueur juste avant)
  • data = writeString(data, (String)dirsRef[i][1]);
  • }
  • //--- la partie fichiers ---
  • //on écrit la version de la partie fichiers
  • data = writeInt(data, FILELIST_DATA_VERSION);
  • //on écrit le nombre de blocs d'informations
  • data = writeInt(data, items.size());
  • for(SuperCopierListItem item : items)
  • {
  • //on récupère et on écrit l'ID du blocs d'informations des dossiers liés
  • String key = item.getDirSrc() + "|" + item.getDirDest();
  • int idDir = (Integer)dirs.get(key)[2];
  • data = writeInt(data, idDir);
  • //on écrit la chaîne du nom de fichier source (avec sa longueur juste avant)
  • data = writeString(data, item.getFileNameSrc());
  • //on écrit la chaîne du nom de fichier de destination (avec sa longueur juste avant)
  • data = writeString(data, item.getFileNameDest());
  • //on écrit la taille du fichier
  • data = writeInt64(data, item.getFileSize());
  • }
  • //on écrit le fichier SCL
  • Tools.writeStream(fileName, data);
  • }
  • /**
  • * Lit l'entier (int) présent dans les 4 prochains octets à partir du décalage courant.
  • *
  • * La lecture se fait en little-endian.
  • *
  • * @param data les données
  • * @param offset le décalage
  • * @return l'entier lu
  • */
  • private static int readInt(byte[] data, int offset)
  • {
  • return data[offset+3] << 24 | data[offset+2] << 16 | data[offset+1] << 8 | data[offset];
  • }
  • /**
  • * Lit l'entier 64 (int64) présent dans les 8 prochains octets à partir du décalage courant.
  • *
  • * La lecture se fait en little-endian.
  • *
  • * @param data les données
  • * @param offset le décalage
  • * @return l'entier lu
  • */
  • private static long readInt64(byte[] data, int offset)
  • {
  • return ((long)data[offset+7] & 0xff) << 56 | ((long)data[offset+6] & 0xff) << 48 | ((long)data[offset+5] & 0xff) << 40 | ((long)data[offset+4] & 0xff) << 32 | ((long)data[offset+3] & 0xff) << 24 | ((long)data[offset+2] & 0xff) << 16 | ((long)data[offset+1] & 0xff) << 8 | ((long)data[offset] & 0xff);
  • }
  • /**
  • * Lit la chaîne de longueur spécifiée à partir du décalage courant.
  • *
  • * Voir le description de la classe pour les détails d'encodage d'une chaîne.
  • *
  • * @param data les données
  • * @param offset le décalage
  • * @param lenght la longueur de la chaîne (et non pas la longueur en octets)
  • * @return la chaîne lue
  • */
  • private static String readString(byte[] data, int offset, int lenght)
  • {
  • String str = "";
  • lenght *= 2;
  • //on passe un octet sur deux
  • for(int i=0; i < lenght; i+=2)
  • str += (char)data[offset + i];
  • return str;
  • }
  • /*
  • * Permet de vérifier la signature du fichier SCL.
  • *
  • * @param vrai si la signature a pu être vérifiée, faux sinon
  • */
  • private static boolean checkSignature(byte[] data)
  • {
  • if(data.length > SCL_SIGNATURE.length) //s'il n'y a déjà pas assez de données pour comparer, on abandonne directement
  • {
  • for(int i=0; i < SCL_SIGNATURE.length; i++)
  • {
  • if(data[i] != SCL_SIGNATURE[i])
  • return false;
  • }
  • }
  • else
  • return false;
  • return true;
  • }
  • /**
  • * Ecris l'entier (int) à la fin des données fournies (en allouant systématiquement la place nécessaire).
  • *
  • * L'écriture se fait en little-endian.
  • *
  • * @param data les données
  • * @param value la valeur a ajouter
  • * @return le résultat
  • */
  • private static byte[] writeInt(byte[] data, int value)
  • {
  • //on alloue l'espace supplémentaire nécessaire
  • int oldSize = data.length;
  • data = Arrays.copyOf(data, oldSize + 4);
  • data[oldSize] = (byte)(value);
  • data[oldSize+1] = (byte)(value >> 8);
  • data[oldSize+2] = (byte)(value >> 16);
  • data[oldSize+3] = (byte)(value >> 24);
  • return data;
  • }
  • /**
  • * Ecris l'entier 64 (int64) à la fin des données fournies (en allouant systématiquement la place nécessaire).
  • *
  • * L'écriture se fait en little-endian.
  • *
  • * @param data les données
  • * @param value la valeur a ajouter
  • * @return le résultat
  • */
  • private static byte[] writeInt64(byte[] data, long value)
  • {
  • //on alloue l'espace supplémentaire nécessaire
  • int oldSize = data.length;
  • data = Arrays.copyOf(data, oldSize + 8);
  • data[oldSize] = (byte)(value);
  • data[oldSize+1] = (byte)(value >> 8);
  • data[oldSize+2] = (byte)(value >> 16);
  • data[oldSize+3] = (byte)(value >> 24);
  • data[oldSize+4] = (byte)(value >> 32);
  • data[oldSize+5] = (byte)(value >> 40);
  • data[oldSize+6] = (byte)(value >> 48);
  • data[oldSize+7] = (byte)(value >> 56);
  • return data;
  • }
  • /**
  • * Ecrit la chaîne à la suite des données fournies (en allouant systématiquement la place nécessaire).
  • *
  • * La taille de la chaîne est automatiquement ajoutée avant celle-ci.
  • * Voir le description de la classe pour les détails d'encodage d'une chaîne.
  • *
  • * @param data les données
  • * @param str la chaîne à écrire
  • * @return le résultat
  • */
  • static private byte[] writeString(byte[] data, String str)
  • {
  • //on écrit la taille de la chaîne qui va suivre
  • data = writeInt(data, str.length());
  • //on alloue l'espace supplémentaire nécessaire
  • int oldSize = data.length;
  • data = Arrays.copyOf(data, oldSize + (str.length() * 2));
  • //on écrit deux octets à chaque fois
  • for(int i=0; i < str.length(); i++)
  • {
  • data[oldSize+(i*2)] = (byte)str.charAt(i);
  • data[oldSize+(i*2)+1] = 0x00;
  • }
  • return data;
  • }
  • /**
  • * Créé un tableau de données contenant la signature d'un fichier SCL en son debut.
  • *
  • * @return le tableau de données
  • */
  • private static byte[] writeSignature()
  • {
  • return Arrays.copyOf(SCL_SIGNATURE, SCL_SIGNATURE.length);
  • }
  • }
package scl;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Vector;

/**
 * Permet de lire et de créer des fichiers .SCL (SuperCopier List) en version 1.
 *
 * Voici les spécifications de l'encodage du fichier :
 *  - Un fichier SCL est un fichier binaire.
 *  - Les valeurs numériques int et int64 sont encodées en little-endian.
 *  - Les chaînes de caractères sont encodés sous la forme : CHAR1 0x00 CHAR2 0x00 CHAR3 0x00 ...,
 *    Il est donc primordial de connaître la longueur de la chaîne avant de la lire. Cette longueur précède donc à chaque fois une chaîne.
 *    Cependant, cette longueur donne le nombre de caractère d'une chaîne. EX: test = longueur 4. Etant donné que chaque caractère utilise 2 octets (le caractère et 0x00), on doit doubler la longueur pour obtenir le nombre d'octets à lire.
 *  - Le fichier SCL peut-être décomposé en trois parties logiques : l'en-tête, la partie des dossiers et la partie des fichiers.
 *
 * La partie en-tête :
 * --------------------
 *  Les 16 premiers octets sont la signature (magic paquet) permettant de confirmer que l'on traite bien un fichier SCL.
 *  Les 4 octets suivants donnent le numéro de version du fichier SCL.
 *
 * La partie dossiers :
 * --------------------
 *  Chaque bloc d'informations donne 3 valeurs : un id, un dossier source et un dossier destination.
 *
 *  Cette partie commence par la version de la partie dossiers sur 4 octets. S'en suit directement le nombre de blocs présents, toujours sur 4 octets.
 *
 *  A la suite de cela sont directement les blocs. Chaque bloc est donc constitué de trois informations :
 *   - l'id est codé sur les 4 premiers octets. Cette ID peut tout simplement être ignoré car, à la suite d'un bug dans le logiciel SuperCopier, la valeur sera toujours 0xff 0xff 0xff 0xff
 *   - les 4 octets suivants donne la taille de la chaîne représentant le répertoire source
 *   - les [longueur * 2] octets suivants représentent la chaîne de caractère du répretoire source
 *   - les 4 octets suivants donne la taille de la chaîne représentant le répertoire de destination
 *   - les [longueur * 2] octets suivants représentent la chaîne de caractère du répertoire de destination
 *
 *  Ces blocs d'informations sont importants les fichiers sont liés à ceux-ci. Chaque fichier possède un ID qui donne le bloc d'informations auquel il est lié.
 *  Les blocs d'informations des dossiers sont donnés dans l'ordre inverse de leur ID. Par ex: le dernier bloc doit avoir l'ID 0, le bloc précédent l'ID 1, ... le dernier bloc l'ID [NB_BLOCS-1].
 *
 * La partie fichiers :
 * ---------------------
 *  Chaque bloc d'informations donne 3 valeurs : l'id du bloc d'informations de la partie "dossiers" auquel le fichier est lié, le nom du fichier source, le nom du fichier destination et la taille du fichier.
 *
 *  Cette partie commence par la version de la partie dossiers sur 4 octets. S'en suit directement le nombre de blocs présents, toujours sur 4 octets.
 *
 *  A la suite de cela sont directement les blocs. Chaque bloc est donc constitué de trois informations :
 *   - l'id du bloc d'informations des dossiers est codé sur 4 octets.
 *   - les 4 octets suivants donne la taille de la chaîne représentant le nom du fichier source
 *   - les [longueur * 2] octets suivants représentent la chaîne de caractère de nom du fichier source
 *   - les 4 octets suivants donne la taille de la chaîne représentant le nom du fichier de destination
 *   - les [longueur * 2] octets suivants représentent la chaîne de caractère du nom du fichier de destination
 *   - les 8 octets suivants donne la taille du fichier
 */
public class SuperCopierList
{
    /**
     * La signature d'en-ête d'un fichier SCL
     */
    private static final byte[] SCL_SIGNATURE = new byte[] { 0x53, 0x43, 0x32, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x20, 0x20, 0x20 };

    /**
     * La version du fichier SCL
     */
    private static final int COPIER_DATA_VERSION = 1;

    /**
     * La version de la partie dossiers du fichier SCL
     */
    private static final int DIRLIST_DATA_VERSION = 1;

    /**
     * La version de la partie fichiers du fichier SCL
     */
    private static final int FILELIST_DATA_VERSION = 1;

    /**
     * Lit le contenu d'un fichier SCL et extrait une liste d'éléments.
     * 
     * Si le fichier est mal formaté, rien n'est p
     *
     * @param fileName le chemin complet vers le fichier SCL à ouvrir
     * @return la lite des fichiers
     * @throws IllegalArgumentException s'il le fichier n'est pas un SCL, s'il s'agit d'une version non supporté ou que le fichier est corrompu
     */
    public static Vector<SuperCopierListItem> read(String fileName)
    {
        try {
            //on récupère les données du fichier
            byte[] data = Tools.readStream(fileName);

            //on contrôle la signature d'en-tête
            if(!checkSignature(data))
                throw new IllegalArgumentException("Incorrect file's signature");

            int offset = SCL_SIGNATURE.length;

            //on contrôle la version du fichier SCL et la version de la partie dossiers
            if(readInt(data, offset) != COPIER_DATA_VERSION || readInt(data, offset+4) != DIRLIST_DATA_VERSION)
                    throw new IllegalArgumentException("Version not supported");

            //on extrait le nombre de blocs d'informations des dossiers
            offset += 8;
            int countDirs = readInt(data, offset);
            offset += 4;

            //on parcourt les blocs d'informations des dossiers
            String[][] dirs = new String[countDirs][2];
            for(int i=0; i < countDirs; i++)
            {
                //les valeurs sont lus par la fin (dernier element lu doit avoir l'index 0 et le premier countDirs-1)
                int index = countDirs-1-i;

                //l'id du dossier, doit être ignoré
                int idDir = readInt(data, offset);
                offset += 4;

                //la longueur de la chaîne du dossier source
                int lenghtDir1 = readInt(data, offset);
                offset += 4;

                //la chaîne du dossier source
                dirs[index][0] = readString(data, offset, lenghtDir1);
                offset += (lenghtDir1 * 2);

                //la longueur de la chaîne du dossier de destination
                int lenghtDir2 = readInt(data, offset);
                offset += 4;

                //la chaîne du dossier de destination
                dirs[index][1] = readString(data, offset, lenghtDir2);
                offset += (lenghtDir2 * 2);
            }

            //on contrôle la version de la partie fichiers
            if(readInt(data, offset) != FILELIST_DATA_VERSION)
                    throw new IllegalArgumentException("Version not supported");

            //on extrait le nombre de blocs d'informations des fichiers
            offset += 4;
            int countFiles = readInt(data, offset);
            offset += 4;

            Vector<SuperCopierListItem> items = new Vector<SuperCopierListItem>();

            //on parcout les blocs d'informations des fichiers
            for(int i=0; i < countFiles; i++)
            {
                //l'id du bloc d'informations des dossiers à lier
                int idDir = readInt(data, offset);
                offset += 4;

                //la longueur de la chaîne du nom de fichier source
                int lenghtDir1 = readInt(data, offset);
                offset += 4;

                //la chaîne du nom de fichier source
                String fileSrc = readString(data, offset, lenghtDir1);
                offset += (lenghtDir1 * 2);

                //la longueur de la chaîne du nom de fichier de destination
                int lenghtDir2 = readInt(data, offset);
                offset += 4;

                //la chaîne du nom de fichier de destination
                String fileDst = readString(data, offset, lenghtDir2);
                offset += (lenghtDir2 * 2);

                //la longueur du fichier
                long fileSize = readInt64(data, offset);
                offset += 8;

                //on ajoute l'élément
                items.add(new SuperCopierListItem(dirs[idDir][0], dirs[idDir][1], fileSrc, fileDst, fileSize));
            }

            return items;
        } catch(ArrayIndexOutOfBoundsException e) { //s'il on lit trop loin c'est que le fichier est corrompu ou incomplet
            throw new IllegalArgumentException("File's corrupted");
        }
    }

    public static void write(Vector<SuperCopierListItem> items, String fileName)
    {
        //--- en-tête ---
        byte[] data = writeSignature();
        data = writeInt(data, COPIER_DATA_VERSION);

        //--- la partie dossier ---
        Map<String, Object[]> dirs = new HashMap<String, Object[]>(); //on utilise un HashMap pour accélerer la recherche
        Object[][] dirsRef = new Object[items.size()][3]; //on utilise ce tableau pour référencer les blocs d'informations par rapport à l'ID donné au bloc
        int index = 0;
        for(SuperCopierListItem item : items)
        {
            String key = item.getDirSrc() + "|" + item.getDirDest();

            if(!dirs.containsKey(key)) //si on ne trouve pas de correspondance, ce tuple d'informations de dossiers n'existe pas encore
            {
                Object[] blocDatas = new Object[] { item.getDirSrc(), item.getDirDest(), index};

                dirsRef[index] = blocDatas; //on place la référence dans le tableau
                dirs.put(key, blocDatas); //on créé le bloc d'informations en lui associant un ID pour faire le lien avec les fichiers
                index++;
            }
        }

        //on écrit la version de la partie dossier
        data = writeInt(data, DIRLIST_DATA_VERSION);

        //on écrit le nombre de blocs d'informations
        data = writeInt(data, dirs.size());

        //on écrit les blocs d'informations dans l'ordre inverse
        for(int i=index-1; i >= 0; i--)
        {
            //on écrit l'ID du bloc à 0xff 0xff 0xff 0xff (à la suite d'un bug dans SuperCopier)
            data = writeInt(data, -1);

            //on écrit la chaîne du dossier source (avec sa longueur juste avant)
            data = writeString(data, (String)dirsRef[i][0]);

            //on écrit la chaîne du dossier de destination (avec sa longueur juste avant)
            data = writeString(data, (String)dirsRef[i][1]);
        }

        //--- la partie fichiers ---
        //on écrit la version de la partie fichiers
        data = writeInt(data, FILELIST_DATA_VERSION);

        //on écrit le nombre de blocs d'informations
        data = writeInt(data, items.size());

        for(SuperCopierListItem item : items)
        {
            //on récupère et on écrit l'ID du blocs d'informations des dossiers liés
            String key = item.getDirSrc() + "|" + item.getDirDest();
            int idDir = (Integer)dirs.get(key)[2];
            data = writeInt(data, idDir);

            //on écrit la chaîne du nom de fichier source (avec sa longueur juste avant)
            data = writeString(data, item.getFileNameSrc());

            //on écrit la chaîne du nom de fichier de destination (avec sa longueur juste avant)
            data = writeString(data, item.getFileNameDest());

            //on écrit la taille du fichier
            data = writeInt64(data, item.getFileSize());
        }

        //on écrit le fichier SCL
        Tools.writeStream(fileName, data);
    }

    /**
     * Lit l'entier (int) présent dans les 4 prochains octets à partir du décalage courant.
     *
     * La lecture se fait en little-endian.
     *
     * @param data les données
     * @param offset le décalage
     * @return l'entier lu
     */
    private static int readInt(byte[] data, int offset)
    {
        return data[offset+3] << 24 | data[offset+2] << 16 | data[offset+1] << 8 | data[offset];
    }

    /**
     * Lit l'entier 64 (int64) présent dans les 8 prochains octets à partir du décalage courant.
     *
     * La lecture se fait en little-endian.
     *
     * @param data les données
     * @param offset le décalage
     * @return l'entier lu
     */
    private static long readInt64(byte[] data, int offset)
    {
        return ((long)data[offset+7] & 0xff) << 56 | ((long)data[offset+6] & 0xff) << 48 | ((long)data[offset+5] & 0xff) << 40 | ((long)data[offset+4] & 0xff) << 32 | ((long)data[offset+3] & 0xff) << 24 | ((long)data[offset+2] & 0xff) << 16 | ((long)data[offset+1] & 0xff) << 8 | ((long)data[offset] & 0xff);
    }

    /**
     * Lit la chaîne de longueur spécifiée à partir du décalage courant.
     *
     * Voir le description de la classe pour les détails d'encodage d'une chaîne.
     *
     * @param data les données
     * @param offset le décalage
     * @param lenght la longueur de la chaîne (et non pas la longueur en octets)
     * @return la chaîne lue
     */
    private static String readString(byte[] data, int offset, int lenght)
    {
        String str = "";
        lenght *= 2;

        //on passe un octet sur deux
        for(int i=0; i < lenght; i+=2)
            str += (char)data[offset + i];
        
        return str;
    }

    /*
     * Permet de vérifier la signature du fichier SCL.
     *
     * @param vrai si la signature a pu être vérifiée, faux sinon
     */
    private static boolean checkSignature(byte[] data)
    {
        if(data.length > SCL_SIGNATURE.length) //s'il n'y a déjà pas assez de données pour comparer, on abandonne directement
        {
            for(int i=0; i < SCL_SIGNATURE.length; i++)
            {
                if(data[i] != SCL_SIGNATURE[i])
                    return false;
            }
        }
        else
            return false;

        return true;
    }

    /**
     * Ecris l'entier (int) à la fin des données fournies (en allouant systématiquement la place nécessaire).
     *
     * L'écriture se fait en little-endian.
     *
     * @param data les données
     * @param value la valeur a ajouter
     * @return le résultat
     */
    private static byte[] writeInt(byte[] data, int value)
    {
        //on alloue l'espace supplémentaire nécessaire
        int oldSize = data.length;
        data = Arrays.copyOf(data, oldSize + 4);

        data[oldSize] = (byte)(value);
        data[oldSize+1] = (byte)(value >> 8);
        data[oldSize+2] = (byte)(value >> 16);
        data[oldSize+3] = (byte)(value >> 24);

        return data;
    }

    /**
     * Ecris l'entier 64 (int64) à la fin des données fournies (en allouant systématiquement la place nécessaire).
     *
     * L'écriture se fait en little-endian.
     *
     * @param data les données
     * @param value la valeur a ajouter
     * @return le résultat
     */
    private static byte[] writeInt64(byte[] data, long value)
    {
        //on alloue l'espace supplémentaire nécessaire
        int oldSize = data.length;
        data = Arrays.copyOf(data, oldSize + 8);

        data[oldSize] = (byte)(value);
        data[oldSize+1] = (byte)(value >> 8);
        data[oldSize+2] = (byte)(value >> 16);
        data[oldSize+3] = (byte)(value >> 24);
        data[oldSize+4] = (byte)(value >> 32);
        data[oldSize+5] = (byte)(value >> 40);
        data[oldSize+6] = (byte)(value >> 48);
        data[oldSize+7] = (byte)(value >> 56);

        return data;
    }

    /**
     * Ecrit la chaîne à la suite des données fournies (en allouant systématiquement la place nécessaire).
     *
     * La taille de la chaîne est automatiquement ajoutée avant celle-ci.
     * Voir le description de la classe pour les détails d'encodage d'une chaîne.
     *
     * @param data les données
     * @param str la chaîne à écrire
     * @return le résultat
     */
    static private byte[] writeString(byte[] data, String str)
    {
        //on écrit la taille de la chaîne qui va suivre
        data = writeInt(data, str.length());

        //on alloue l'espace supplémentaire nécessaire
        int oldSize = data.length;
        data = Arrays.copyOf(data, oldSize + (str.length() * 2));

        //on écrit deux octets à chaque fois
        for(int i=0; i < str.length(); i++)
        {
            data[oldSize+(i*2)] = (byte)str.charAt(i);
            data[oldSize+(i*2)+1] = 0x00;
        }

        return data;
    }

    /**
     * Créé un tableau de données contenant la signature d'un fichier SCL en son debut.
     * 
     * @return le tableau de données
     */
    private static byte[] writeSignature()
    {
        return Arrays.copyOf(SCL_SIGNATURE, SCL_SIGNATURE.length);
    }
}


 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

07 septembre 2010 21:53:05 :
Un petit oubli

 Sources de la même categorie

Source avec Zip Source avec une capture [J2ME] MAILXPRESS, UNE PETITE APPLICATION D'ENVOI DE MAIL ÉC... par doderic
Source avec Zip CLIENT ET SERVEUR DE MESSAGERIES par lemout
Source avec Zip Source avec une capture NAVIGATEUR HTTP par lemout
Source avec Zip Source avec une capture PROGRAMME DE PARTAGE DE FICHIER EN RESEAUX par billatosco
Source avec Zip JET SPRING JSF PRIMEFACES par mendjijet

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture NETTOYEUR DE LIGNES DE CODES PRISES SUR CODES-SOURCES.COM par z980x
Source avec Zip CLASSE UTILE POUR LES FICHIERS par AbriBus

Commentaires et avis

Aucun commentaire pour le moment.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

copier un repertoire à partir d'un archive [ par aaqil ] j'ai un archive "archive.jar" qui contient un repertoire "rep" .Dans un programme java, comment copier ce repertoire à partir de l'archive dans un emp Copier des fichiers a partir de leurs adresses [ par RustyNail ] Voila mon probleme:J'ai une base de données qui contient des adresses de fichiers videos, je voudrais developper une application java qui lit la bd et Probleme pour le copier coller en java [ par Frouf85 ] Bonjour bonjour...Si vous vouliez bien me venir en aide, ca serait sympa!En fait mon copier/coller ne marche pas.Voila mon code:import java.awt.datatr Comment faire pour copier le contenu (avec plusieurs style) d'1 JTextPane vers un autre JTextPane? [ par coinki ] Bonjour à tous,Ma question est donc comment faire pour copier le contenu d'un JTextPane vers un autre JTextPane, sachant que je veux aussi copier si p Partie server d'un chat en applet [ par juanpipo ] Salut a tous,dans le cadre de mon stage je dois faire un chat en java et je n'arrive pas a lancer ma partie server, je ne c pas pkoi ca plante. Merci Erreur bouquin [ par kitof7 ] Bonjour, je suis autodidacte et j'essaie d'apprendre JAVA à partir d'un bouquin.J'ai pas accés à mon ordi pour le moment -&gt; je ne peut donc pas tes copier des données d'un fichier texte vers une jtable [ par kaliel ] bonjour, je débute en java et ma questiob est peut être simple mais bon.je voudrais envoyer des données qui sont dans un fichier texte du style:1,"nom Filtre [ par EducJava ] Salut,Est-ce possible de faire cela en java ?J'ai une page HTML que je dois copier dans une nouvelle page .dat mais je ne dois pas copier toute la pag Copier un objet ET NON SA REFERENCE dans une variable [ par darkstorm ] Bonjour,Mon problème est le suivant :si je faisArrayList copie;ArrayList objet=new ArrayList();objet.add("Salut");copie=objet;je copie la référence de [JTree] Poblème de Copier/Coller [ par breed1200 ] Salut à tous!Je fais un soft avec un JTree composé de DefaultMutableTreeNode qui contiennent des Objets persos. J'ai implémenté le Drag n drop sans so


Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,014 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales