Mission 1 : Archivage de données en C#

Contexte : Pour préparer la migration des données, il faudrait créer un script C# qui permettra de récupérer tous les fichiers et les copier dans plusieurs fichiers zip dans un dossier précis.

App.Config : Ce fichier est le fichier de configuration du projet c#. On y trouvera

une section avec les clés correspondants au nom des dossiers où se trouvent les

fichiers, et qui ont pour valeur le chemin permettant d'accéder à ce dossier.

Il y a cependant une clé nommée LastRun qui a pour valeur une date initialisée

"01/01/2000 00:00:00" qui sera comparée à la date de modification de chaque

fichier. Si la date du fichier est antérieure à celle de LastRun, on ne la compte pas

parmi les fichiers à zipper. LastRun sera mis à jour après le lancement du script.


ConfigReader.cs : Ce fichier constitue le coeur du projet. C'est ici que toutes les

fonctions seront programmées.

ArchiveConfig - une classe scellée contenant des variables ayant pour nom les

clés de la section App.Config.


Program.cs : Il s'agit du fichier où nous allons appeler la fonction principale pour

archiver les fichiers.

Détail des fonctions :

J'ai commencé par créer une classe scellée, qui comportera uniquement des

variables qui seront utilisées plus tard.

La première fonction créée est ReadConfiguration().

Cette fonction a pour but de récupérer les valeurs présente dans l'App.Config.

Les premières lignes permettent d'ouvrir le fichier de configuratin App.Config,

et d'utiliser l'environnement que nous souhaitons. Ici, l'environnement est CLK.

Avant de récupérer les valeurs, il faut vérifier si la section CLK n'est pas vide.

Toutes les valeurs du App.Config sont des chaines de caractères sauf pour

LastRun qui est une date.

On créé donc un dictionnaire config.PathDict pour récupérer les valeurs

correspondant au chemin de chaque dossier à zipper et un second dictionnaire

config.TargetPathDict pour récupérer le chemin de destination pour chaque zip.

On remarque également que la longueur du dictionnaire TargetPathDict est plus

long que le premier. En effet, il y a deux clés en plus. MAX_ZIP_SIZE_BYTE et

MAX_NUM_OF_FILES_IN_ZIP correspondant à la limite de bits et de fichiers par

zip. Ils ne seront pas comptés car la boucle d'archivage de fichier se fera sur

le premier dictionnaire PathDict.


La deuxième fonction est une private fonction nommée getConfigValue prenant

en paramètre une chaine de caractères. Cette fonction va simplement renvoyer la

valeur associée à la clé du App.config. Elle sera utilisée dans la fonction qui suit.

La prochaine fonction à créer est une procédure qui permet de zipper un certains

nombre de fichiers.

La fonction se nomme CompressToZip qui prend en paramètre le chemin de

destination, le nom du fichier choisi pour le ZIP qui va être le nom de chaque clé

(qui correspond au nom de chaque dossier à zipper) suivi de la date "06152023"

du fichier le plus ancien et du plus récent (ex : TEST_06102023_06152023.zip), et

une liste qui comportera les fichiers à mettre dans un fichier ZIP. Le niveau de

compression est à 9 car c'est le niveau de compression le plus élevé. Il est

possible qu'il y ai parfois deux fichiers ZIP avec le même nom. Pour éviter cela,

j'ai crée une condition qui ajoute un suffixe (_1, _2...) si il existe déjà un fichier

ZIP avec le nom entré en paramètre.

La dernière fonction est la fonction principale où les fonctions précédentes sont

utilisées. La fonction se nomme Archive().

Pour commencer, j'ai crée une variable i dans un boucle qui va parcourir les

chemin de dossiers sources, qui correspond à l'index dans le

dictionnaire targetPath, où se trouve le chemin de destination des fichiers. A

chaque tour de boucle, on change de dossier source donc on ajoute 1 à i pour

changer de dossier de destination.

Dans cette première boucle, on y trouve deux autres variables : actualFileCount

et actualSizeOfFiles.

Nous souhaitons que pour chaque fichier ZIP, il y ait un maximum de 100 fichiers

ou que le fichier ZIP ait une taille maximale de 20 Mo. actualFileCount est utilisé

pour compter le nombre de fichier qu'on va mettre dans un fichier ZIP, et

actualSizeOfFile pour compter le nombre total de bits pour un nombre de

fichiers. Le chemin de chaque fichier seront mis dans une liste nommée pathList.

C'est à chaquefois que l'on va ajouter un fichier dedans, que l'on va actualiser

actualFileCount et actualSizeOfFile. Pour ajouter la taille d'un fichier (int) dans

notre variable, on utilise .Lenght.

Etant donné que l'on veut pour chaque fichier ZIP un nom avec la date du fichier

le plus ancien et le plus récent, nous devons parcourir les fichiers rangé par date

de création. C'est le meilleur moyen pour trouver la date la plus ancienne et la

plus récente, car le fichier le plus ancien se trouve à l'index 0 de la liste des

fichiers, et le fichier le plus récent au dernier index.

La première chose à faire lorsque l'on parcourt les fichiers, est de vérifier

longueur du nom chemin du fichier. Pourquoi? Car sa longueur ne peut pas


dépasser une taille de 260 caractères. Donc si le fichier en cours d'utilisation


a une taille supérieure à 260 caractères, on affiche un message d'erreur (détail

du log plus tard...) et on continue notre boucle.

Les conditions ont un ordre très précis pour éviter tout problème lors de

l'archivage. La seconde condition vérifie si la taille du fichier est supérieur à la

taille maximale définie pour un fichier ZIP. Si c'est le cas, on crée va zipper ce

fichier seul et continuer la boucle.

La troisième condition vérifie si la liste des fichiers à atteint son maximum en

terme de nombre de fichier OU en terme de taille. Si un des deux est vrai, on zip

les fichiers présent dans la liste.

Pour chaque fichier, on vérifie si sa date est au dessus de LastRun et si c'est le

cas, on l'ajoute à la liste des fichiers à zipper et on met à jour les compteurs

actualFileCount et actualSizeOfFiles. Sinon, on renvoie une erreur.

Enfin, si la liste contient au moins un fichier, on le zippe.

Pour en revenir au logger, un log permet d'afficher des informations lorsque le

programme est en cours. Le log utiliser vient de Log4Net est il est très efficace.

J'ai fait en sorte d'afficher les informations dans un fichier log.txt pour que les

personnes qui souhaitent utiliser mon code puisse accéder à ces informations.

Il est pratique d'utiliser un log car il nous permet de voir si il y a certains

problème et d'avertir (dans mon cas), si un fichier ne peut pas être archivé.

Il y a plusieurs types de messages : INFO, DEBUG, ERROR et WARN et FATAL.

J'ai uniquement utilisé INFO et ERROR.

Voici le résultat final (une partie seulement) :

Ici une partie de l'archivage. Le nom du dossier avec la date du fichier le plus

ancien et du plus récent.

Et le log (exemple) :



MISSION 1 TERMINÉE