Question

System.IO.Compression.GZipStream ou System.IO.Compression.Deflate sont-ils compatibles avec la compression zlib?

Était-ce utile?

La solution

De MSDN à propos de System.IO .Compression.GZipStream:

  

Cette classe représente le format de données gzip, qui utilise un algorithme standard pour la compression et la décompression de fichiers sans perte.

À partir de la FAQ sur zlib :

  

Les fonctions gz * dans zlib utilisent en revanche le format gzip.

Donc, zlib et GZipStream devraient être interopérables, mais uniquement si vous utilisez les fonctions zlib pour gérer le format gzip.

System.IO.Compression.Deflate et zlib ne seraient apparemment pas interopérables.

Si vous devez gérer des fichiers zip (probablement pas vous, mais quelqu'un d'autre pourrait en avoir besoin), vous devez utiliser SharpZipLib ou une autre bibliothèque tierce.

Autres conseils

DotNetZip comprend un DeflateStream, un ZlibStream et un GZipStream, permettant de gérer les RFC 1950, 1951 et 1952. Tous utilisent l’algorithme DEFLATE mais les octets d’encadrement et d’en-tête sont différents pour chacun.

Comme avantage, les flux dans DotNetZip ne présentent pas l’ anomalie de extension de la taille des données en cours de compression, rapportée aux flux intégrés. De plus, il n'y a pas de ZlibStream intégré, alors que DotNetZip vous le permet, pour une bonne interopérabilité avec zlib.

J'ai rencontré ce problème avec les objets Git. Dans ce cas particulier, ils stockent les objets sous forme de blobs dégonflés avec un en-tête Zlib, documentés dans la RFC 1950. . Vous pouvez créer un blob compatible en créant un fichier contenant:

  • Deux octets d'en-tête (CMF et FLG de RFC 1950) avec les valeurs 0x78 0x01
    • CM = 8 = dégonfler
    • CINFO = 7 = fenêtre 32 Ko
    • FCHECK = 1 = bits de somme de contrôle pour cet en-tête
  • La sortie du DeflateStream
  • de C #
  • Somme de contrôle Adler32 des données d'entrée dans le DeflateStream , format big-endian (MSB en premier)

J'ai créé ma propre implémentation Adler

public class Adler32Computer
{
    private int a = 1;
    private int b = 0;

    public int Checksum
    {
        get
        {
            return ((b * 65536) + a);
        }
    }

    private static readonly int Modulus = 65521;

    public void Update(byte[] data, int offset, int length)
    {
        for (int counter = 0; counter < length; ++counter)
        {
            a = (a + (data[offset + counter])) % Modulus;
            b = (b + a) % Modulus;
        }
    }
}

Et c'était à peu près tout.

J'ai utilisé GZipStream pour compresser la sortie du .NET XmlSerializer et cela a parfaitement fonctionné pour décompresser le résultat avec gunzip (en cygwin), winzip et un autre GZipStream.

Pour référence, voici ce que j'ai fait dans le code:

FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
using (GZipStream gzStream = new GZipStream(fs, CompressionMode.Compress))
{
  XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
  serializer.Serialize(gzStream, myData);
}

Ensuite, pour décompresser en c #

FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
using (Stream input = new GZipStream(fs, CompressionMode.Decompress))
{
   XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
   myData = (MyDataType) serializer.Deserialize(input);
}

L'utilisation de l'utilitaire 'file' dans cygwin révèle qu'il existe bien une différence entre le même fichier compressé avec GZipStream et GNU GZip (probablement des informations d'en-tête comme d'autres l'ont indiqué dans ce fil). Cette différence ne semble toutefois pas avoir d’importance dans la pratique.

gzip est deflate + certaines données d'en-tête / pied de page, telles qu'une somme de contrôle et une longueur, etc. Elles ne sont donc pas compatibles, en ce sens qu'une méthode peut utiliser un flux de l'autre, mais utilise le même algorithme de compression. / p>

Ils ne font que compresser les données à l’aide d’algorithmes zlib ou deflate, mais ne fournissent pas la sortie pour un format de fichier spécifique. Cela signifie que si vous stockez le flux tel quel sur le disque dur, vous ne pourrez probablement pas l'ouvrir à l'aide d'une application (gzip ou winrar), car les en-têtes de fichier (numéro magique, etc.) ne sont pas inclus dans le flux. écrivez-les vous-même.

À partir de .NET Framework 4.5, la classe System.IO.Compression.DeflateStream utilise la bibliothèque zlib.

De la classe Article MSDN :

  

Cette classe représente l'algorithme Deflate, qui est un algorithme standard pour la compression et la décompression de fichiers sans perte. À partir de .NET Framework 4.5, la classe DeflateStream utilise la bibliothèque zlib. En conséquence, il fournit un meilleur algorithme de compression et, dans la plupart des cas, un fichier compressé plus petit que celui fourni dans les versions précédentes du .NET Framework.

Je suis d’accord avec andreas. Vous ne pourrez probablement pas ouvrir le fichier dans un outil externe, mais si cet outil attend un flux, vous pourrez peut-être l'utiliser. Vous pourrez également dégonfler le fichier en utilisant la même classe de compression.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top