Je vais avoir du mal à lire un fichier de données compressées (dégonflé) en utilisant C# .NET DeflateStream(..., CompressionMode.Decompress)
. Le fichier a été écrit plus tôt en utilisant DeflateStream(..., CompressionMode.Compress)
, et il semble être très bien (je peux même le décompresser en utilisant un programme Java).fichier de données Décompresser avec DeflateStream
Cependant, le premier appel Read()
sur le flux d'entrée pour décompresser/gonfler les données compressées renvoie une longueur de zéro (fin du fichier).
est ici le principal moteur, qui est utilisé pour la compression et la décompression:
public void Main(...)
{
Stream inp;
Stream outp;
bool compr;
...
inp = new FileStream(inName, FileMode.Open, FileAccess.Read);
outp = new FileStream(outName, FileMode.Create, FileAccess.Write);
if (compr)
Compress(inp, outp);
else
Decompress(inp, outp);
inp.Close();
outp.Close();
}
Voici le code de base pour la décompression, qui est ce qui est un échec:
public long Decompress(Stream inp, Stream outp)
{
byte[] buf = new byte[BUF_SIZE];
long nBytes = 0;
// Decompress the contents of the input file
inp = new DeflateStream(inp, CompressionMode.Decompress);
for (;;)
{
int len;
// Read a data block from the input stream
len = inp.Read(buf, 0, buf.Length); //<<FAILS
if (len <= 0)
break;
// Write the data block to the decompressed output stream
outp.Write(buf, 0, len);
nBytes += len;
}
// Done
outp.Flush();
return nBytes;
}
L'appel marqué FAILS
toujours renvoie zéro. Pourquoi? Je sais que ça doit être quelque chose de simple, mais je ne le vois pas.
est ici le code de base pour la compression, qui fonctionne très bien et est presque exactement la même que la méthode de décompression avec les noms permutés:
public long Compress(Stream inp, Stream outp)
{
byte[] buf = new byte[BUF_SIZE];
long nBytes = 0;
// Compress the contents of the input file
outp = new DeflateStream(outp, CompressionMode.Compress);
for (;;)
{
int len;
// Read a data block from the input stream
len = inp.Read(buf, 0, buf.Length);
if (len <= 0)
break;
// Write the data block to the compressed output stream
outp.Write(buf, 0, len);
nBytes += len;
}
// Done
outp.Flush();
return nBytes;
}
Résolu
Après avoir vu la bonne solution , l'instruction constructeur doit être remplacée par:
inp = new DeflateStream(inp, CompressionMode.Decompress, true);
qui conserve le flux d'entrée sous-jacent ouvert, et la ligne suivante doit être ajoutée après l'appel inp.Flush()
:
inp.Close();
Les appels Close()
force le flux de deflater pour vider ses tampons internes. Le drapeau true
l'empêche de fermer le flux sous-jacent, qui est fermé plus tard dans Main()
. Les mêmes modifications doivent également être apportées à la méthode Compress()
.
@LoadMaster: BTW: Quand je courais votre code, je n'ai pas eu le même comportement que vous avez décrit, mais ça n'a pas marché non plus. Dans mon cas, le décompresseur a réussi, mais si j'ai comparé le fichier décompressé avec l'original, ils ne correspondaient pas. Le fichier décompressé était plus petit que l'original - octets manquants. La modification que nous appelons close() sur DeflateStream a également résolu ce problème. Je soupçonne que la différence de comportement pourrait juste avoir à faire avec la taille de mon fichier de test contre le vôtre - peut-être qu'il a perdu les N derniers octets, et mon fichier était plus grand (le mien était de 364 391 octets). – JMarsch
Doh. Bien sûr, il est dit dans les documents que vous devez fermer le flux de déflateur pour vous assurer que tous les tampons internes sont correctement vidés. Je devrais appeler 'Close()' sur les flux compresseurs/décompresseurs dans les méthodes 'Decompress()' et Compress() 'car ils contrôlent directement les flux compresseur/décompresseur. Alternativement, je pourrais ouvrir 'DeflaterStream' avec l'indicateur' keepOpen' true pour garder le flux d'entrée sous-jacent ouvert. Je fermerais toujours le flux de déflateur, mais ensuite je ferais aussi fermer le flux de fichier sous-jacent par la suite. J'ai essayé ceci, et cela fonctionne. –