Sauvegarder et lire ses données dans un fichier zip

ZipFileIl est fréquent que l’on sauvegarde ses données dans un fichier. Pour effectuer cette opération, le plus simple (si l’on est un peu fainéant) est d’utiliser l’un des sérialisateurs fourni par le Framework (le plus optimisé est de créer son propre format mais c’est une autre histoire).

Ici, nous allons utiliser le sérialisateur DataContractSerializer, utilisé pour les contrats WCF.

L’inconvénient de ce sérialiseur, c’est qu’il ne cherche absolument pas à optimiser la taille du fichier généré, et comme le format est un format Xml, il est verbeux et donc volumineux.

Vous allez me dire, avec les disques durs que l’on a actuellement, ce n’est pas vraiment un soucis. Oui, sauf que si le fichier, on veut le sauvegarder dans le RoamingFolder pour pouvoir le sauvegarder “in ze cloud”, il va falloir faire attention à ce qu’il ne dépasse pas les 100Ko, sinon il ne sera pas uploadé “in ze cloud” (propriété RoamingStorageQuota).

Donc la bonne idée, enfin celle que j’ai trouvée bonne, consiste donc à zipper le contenu du fichier xml généré par le sérialisateur.

Dans mon exemple, je sérialise une énumération d’objet User :

private async Task WriteToZipFile()
{
    var sw = Stopwatch.StartNew();
    var file = await ApplicationData.Current.RoamingFolder
                                    .CreateFileAsync(
                                        UsersFileName,
                                        CreationCollisionOption.ReplaceExisting);

    // archivage dans le zip
    using (var fileStream = await file.OpenStreamForWriteAsync())
    {
        using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Create, false))
        {
            var entry = archive.CreateEntry(UsersEntry, CompressionLevel.Fastest);
            var serializer = new DataContractSerializer(typeof (IEnumerable<User>));
            serializer.WriteObject(entry.Open(), Users);
        }
    }

    Debug.WriteLine("Sauvegarde ZIP : {0}ms", sw.ElapsedMilliseconds);
}

Et je fais la même chose en sens inverse pour lire le contenu de ce fichier :

private async Task<IEnumerable<User>> ReadFromZipFile()
{
    var sw = Stopwatch.StartNew();

    var file = await ApplicationData.Current.RoamingFolder
                                    .GetFileAsync(UsersFileName);

    // archivage dans le zip
    using (var archive = new ZipArchive(await file.OpenStreamForWriteAsync(), ZipArchiveMode.Read, false))
    {
        var entry = archive.GetEntry(UsersEntry);
        var serializer = new DataContractSerializer(typeof(IEnumerable<User>));
        var result = (IEnumerable<User>) serializer.ReadObject(entry.Open());
        Debug.WriteLine("Lecture : {0}ms", sw.ElapsedMilliseconds);

        return result;
    }
}

Ce n’est pas très compliqué et on gagne énormément de place Clignement d'œil

ATTENTION : l’enregistrement, c’est-à-dire la création du fichier zip est long, très long, donc à utiliser avec parcimonie et pas à toutes les sauces (comme je l’avais fais dans mon code Tire la langue).

blog comments powered by Disqus