GZipStream Et DeflateStream ne sera pas décompresser tous les octets
J'avais besoin d'un moyen de compresser les images dans .net alors j'ai regardé dans l'aide de l' .net GZipStream classe (ou DeflateStream). Cependant j'ai trouvé que la décompression est pas toujours couronnée de succès, parfois, les images de décompresser fine et d'autres fois, je voudrais obtenir un RIB+ erreur que quelque chose est endommagé.
Après avoir enquêté sur la question, j'ai trouvé que cette période n'était pas de donner tous les octets qu'il compressés. Donc, si j'ai compressé 2257974 octets je voudrais parfois revenir seulement 2257870 octets (nombres réels).
Le plus drôle, c'est que, parfois, il serait de travailler. J'ai donc créé ce petit test de la méthode qui comprime seulement 10 octets et maintenant je n'ai pas récupérer quoi que ce soit.
Je l'ai essayé avec les deux classes de compression GZipStream et DeflateStream et j'ai vérifié mon code d'éventuelles erreurs. J'ai même essayé de positionner le flux de 0 et de rinçage de tous les cours d'eau, mais avec pas de chance.
Voici mon code:
public static void TestCompression()
{
byte[] test = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] result = Decompress(Compress(test));
//This will fail, result.Length is 0
Debug.Assert(result.Length == test.Length);
}
public static byte[] Compress(byte[] data)
{
var compressedStream = new MemoryStream();
var zipStream = new GZipStream(compressedStream, CompressionMode.Compress);
zipStream.Write(data, 0, data.Length);
return compressedStream.ToArray();
}
public static byte[] Decompress(byte[] data)
{
var compressedStream = new MemoryStream(data);
var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress);
var resultStream = new MemoryStream();
var buffer = new byte[4096];
int read;
while ((read = zipStream.Read(buffer, 0, buffer.Length)) > 0) {
resultStream.Write(buffer, 0, read);
}
return resultStream.ToArray();
}
- Re votre commentaire, il revient à l'tampons à des niveaux différents; si elles ne sont pas toutes les vidé (dans le bon ordre), alors vous n'obtenez pas toutes les données.
- Remarque, par exemple, que je n'ai pas pris la peine d'appeler Close() sur la MemoryStream lui-même - j'ai donc partiellement d'accord ;-p
- Je vais ajouter une mise à jour sur ce, trop....
- Tout à fait raison. (À un moment j'ai essayé d'utiliser Close() sur le flux de mémoire, mais la méthode ToArray() a été de se plaindre, ce qui voudrait dire que je dois créer un nouveau tampon, vide le cours d'eau sur elle, fermer le flux de données, de retour de la nouvelle mémoire tampon. Juste beaucoup de travail)
- J'ai oublié de dire: c'était une excellente question formulée, dans l'exemple de code, il est très facile de montrer qu'un: il a été brisé, et b: quand il a été fixé. Trois hourras.
Vous devez vous connecter pour publier un commentaire.
Vous devez
Close()
laZipStream
après l'ajout de toutes les données que vous souhaitez compresser; il conserve un tampon non écrites octets en interne (même si vousFlush()
) qui doit être écrit.Plus généralement,
Stream
estIDisposable
, donc vous devriez également êtreusing
chaque... (oui, je sais queMemoryStream
ne va pas perdre toutes les données, mais si vous n'avez pas entrer dans cette habitude, il va vous mordre avec d'autresStream
s).[edit : mise à jour de la ré commentaire]
Re pas
using
des choses commeMemoryStream
- c'est toujours un plaisir, avec beaucoup de votes sur les deux côtés de la clôture: mais ultimatey...(rhétorique - nous connaissons tous la réponse...) Comment est -
MemoryStream
mis en œuvre? est-il un byte[] (détenue par .NET)? est-ce un fichier mappé en mémoire (propriété de l'OS)?La raison pour laquelle vous n'êtes pas
using
c'est parce que vous laissez à la connaissance de la mise en œuvre interne de détails changer la façon dont vous code contre une API publique - c'est à dire que vous venez violé les lois de l'encapsulation. L'API publique dit: je suisIDisposable
; vous "propre" de moi; donc, c'est votre travail pourDispose()
moi quand vous êtes à travers.Aussi garder à l'esprit la DeflateStream dans le Système.IO.La Compression ne pas mettre en œuvre le plus efficace algorithme deflate. Si vous le souhaitez, il existe une alternative à la BCL GZipStream et DeflateStream; il est mis en œuvre dans la gestion complète de la bibliothèque fondée sur zlib code, qui fonctionne mieux que dans le haut-{Dégonfler,GZip}Flux à cet égard. [ Mais vous avez encore besoin de Fermer() le flux pour obtenir le plein bytestream. ]
Ces classes de flux sont expédiés dans les DotNetZlib assemblée, disponible dans le DotNetZip de distribution à http://DotNetZip.codeplex.com/.