Accueil > > > LECTURE ET ÉCRITURE DE FICHIERS SCL (SUPERCOPIER LIST)
LECTURE ET ÉCRITURE DE FICHIERS SCL (SUPERCOPIER LIST)
Information sur la source
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);
}
}
Historique
- 07 septembre 2010 21:53:05 :
- Un petit oubli
Sources de la même categorie
Commentaires et avis
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 -> 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
|
Derniers Blogs
XNA IS DEAD!XNA IS DEAD! par richardc
Depuis la semaine dernière (et grâce aux TechDays 2012), je me penche activement sur la nouvelle version de Windows, aka Windows 8. Vous me direz, il était temps puisque la première preview date de Septembre dernier.
OK. Remarquez, on n'en est qu'aux...
Cliquez pour lire la suite de l'article par richardc TECHDAYS PARIS 2012 : WINDOWS SERVER "8" QUOI DE 9 !TECHDAYS PARIS 2012 : WINDOWS SERVER "8" QUOI DE 9 ! par ROMELARD Fabrice
Speakers: Fabrice Meillon et Stanislas Quastana Cette session est basée entièrement sur celle donnée lors de la BUILD cet hiver. Il n'y a pas d'ajout d'information en rapport avec cet évènement passé. Windows 8 Server sera intégralem...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice [HTML5] AUTOUR DU W3C : NOUVEAUX STANDARDS ET WEB MOBILE (LILLE)[HTML5] AUTOUR DU W3C : NOUVEAUX STANDARDS ET WEB MOBILE (LILLE) par Gio
Je m'y prends un peu tard je sais, mais bon je suis développeur web et donc hyper fainéant ! Toujours dans le cadre des technologies émergentes, ici HTML5, parce qu'on aime HTML5 chez Wyg , nous seront présent, le vieux ( Aurélien V.) et moi, pour pr...
Cliquez pour lire la suite de l'article par Gio [WP7] DYNAMICALLY CHANGE STARTUP PAGE[WP7] DYNAMICALLY CHANGE STARTUP PAGE par KooKiz
Let's say that you want to allow the user to customize the startup page of your application. You can easily change the startup page by editing the 'NavigationPage' attribute in the manifest file. But the manifest cannot be modified once the applicatio...
Cliquez pour lire la suite de l'article par KooKiz
Forum
RE : URL ET JAVARE : URL ET JAVA par Pylouq
Cliquez pour lire la suite par Pylouq
Logiciels
DocTranslate (V3.1.0.0)DOCTRANSLATE (V3.1.0.0)DocTranslate est un traducteur de document Microsoft Word, PowerPoint et Excel. Il permet d'autom... Cliquez pour télécharger DocTranslate Tribler (2012)TRIBLER (2012)Tribler est un client pair à pair (P2P/Peer-to-Peer) open source avec la capacité de regarder des... Cliquez pour télécharger Tribler OneSwarm (2012)ONESWARM (2012)Le peer-to-peer qui protège votre vie privée, c'est OneSwarm.
Ce logiciel de peer-to-peer crypté... Cliquez pour télécharger OneSwarm PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V8.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V8.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System
|