Décompressez le fichier de données avec DeflateStream
Je vais avoir de la difficulté à lire un comprimé (dégonflé) fichier de données à l'aide de C# .NET DeflateStream(..., CompressionMode.Decompress)
. Le fichier a été écrit plus tôt à l'aide de DeflateStream(..., CompressionMode.Compress)
, et il semble être très bien (je peux même le décompresser à l'aide d'un programme Java).
Cependant, la première Read()
appel sur le flux d'entrée pour décompresser/gonfler les données compressées renvoie une longueur de zéro (fin de fichier).
Ici est le conducteur principal, 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 défectueux:
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 a été FAILS
renvoie toujours zéro. Pourquoi? Je sais qu'il faut que ce soit quelque chose de simple, mais je ne suis pas le voir.
Voici le code de base pour la compression, qui fonctionne bien, et est presque exactement la même que la méthode de décompression avec les noms inversé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 solution correcte, le constructeur déclaration doit être modifié pour:
inp = new DeflateStream(inp, CompressionMode.Decompress, true);
qui maintient le sous-jacent flux d'entrée s'ouvrir, et la ligne suivante doit être ajoutée à la suite de la inp.Flush()
appel:
inp.Close();
La Close()
appelle les forces de l'deflater flux de vider ses tampons internes. Le true
drapeau empêche de fermer le flux sous-jacent, qui est fermée plus tard dans Main()
. Les mêmes modifications doivent également être apportées à la Compress()
méthode.
OriginalL'auteur David R Tribble | 2009-10-06
Vous devez vous connecter pour publier un commentaire.
Dans votre décompresser méthode, sont réaffectation des inp à un nouveau Flux (un dégonfler stream). Vous ne fermez jamais que de Dégonfler des flux, mais vous ne la fermez le fichier sous-jacent flux dans main(). Une chose semblable se passe dans le compresser méthode.
Je pense que le problème est que le fichier de flux est fermé avant de le dégonfler stream, finaliseurs sont automatiquement leur fermeture.
J'ai ajouté 1 ligne de code à votre Décompresser et Compresser méthodes:
l'inp.Close() //pour la Decompressmehtod
ax.Close() //pour le compresser méthode.
une meilleure pratique serait de joindre les cours d'eau dans une clause using.
Voici une autre façon d'écrire votre Décompresser méthode (que j'ai testé, et ça marche)
Doh. Bien sûr, il dit qu'il y a droit dans les docs que vous devez fermer les deflater flux pour s'assurer que tous les tampons internes sont éliminés correctement. Je devrais appeler
Close()
sur les compresseurs/décompresseurs cours d'eau dans leDecompress()
etCompress()
méthodes, car ils contrôlent le compresseur/décompresseur flux directement. Sinon, j'ai pu ouvrir leDeflaterStream
avec lekeepOpen
drapeau vrai pour maintenir le sous-jacent flux d'entrée ouverte. Je serais toujours près de la deflater stream, mais je vais aussi fermer la sous-jacentes de flux de fichiers par la suite. J'ai essayé, et ça marche.OriginalL'auteur JMarsch
J'ai eu le même problème avec GZipStream, Depuis que nous avons eu de la longueur initiale stockée, j'ai dû ré-écrire le code pour lire uniquement le nombre d'octets attendus dans le fichier d'origine.
J'espère que je suis sur le point d'apprendre qu'il y avait une meilleure réponse (croisons les doigts).
OriginalL'auteur csharptest.net