Come gonfiare un file con zlib.NET?
-
06-07-2019 - |
Domanda
Sto usando la zlib.NET per provare e gonfiare i file che sono compressi da zlib (su un box Linux, forse). Ecco cosa sto facendo:
zlib.ZInputStream zinput =
new zlib.ZInputStream(File.Open(path, FileMode.Open, FileAccess.Read));
while (stopByte != (data = zinput.ReadByte()))
{
// check data here
}
zinput.Close();
I byte di dati corrispondono ai byte di dati compressi, quindi devo fare qualcosa di sbagliato.
Soluzione 2
Sembra che io abbia fatto l'errore di presumere che tutti i metodi virtuali fossero stati ignorati, il che non era il caso. Stavo usando zlib.ZInputStream.ReadByte (), che è solo Stream.ReadByte () ereditato, che non si gonfia.
Ho usato invece zlib.ZInputStream.Read () e ha funzionato come dovrebbe.
Altri suggerimenti
Oltre a non usare un " usando " dichiarazione per chiudere il flusso anche di fronte a un'eccezione, mi sembra a posto. I dati sono sicuramente compressi? Sei in grado di decomprimerlo con zlib sulla scatola di Linux?
Dopo aver esaminato il codice sorgente, è piuttosto orribile: una chiamata a int Read (buffer, offset, lunghezza)
finirà per chiamare il suo int Read ()
ad esempio il metodo length
. Dato quel tipo di inizio traballante, non sono sicuro che mi fiderei particolarmente del codice, ma mi sarei aspettato che funzionasse almeno leggermente ! Hai provato a utilizzare SharpZipLib ?
Saltando l'intestazione zlib (primi due byte, 78 9C
) e quindi usando DeflateStream
integrato in .net ha funzionato per me.
using(var input = File.OpenRead(...))
using(var output = File.Create(...))
{
// if there are additional headers before the zlib header, you can skip them:
// input.Seek(xxx, SeekOrigin.Current);
if (input.ReadByte() != 0x78 || input.ReadByte() != 0x9C)//zlib header
throw new Exception("Incorrect zlib header");
using (var deflateStream = new DeflateStream(decryptedData, CompressionMode.Decompress, true))
{
deflateStream.CopyTo(output);
}
}
Il codice qui sotto potrebbe aiutarti ragazzi. Crea un'istanza dell'oggetto e usa le funzioni.
public class FileCompressionUtility
{
public FileCompressionUtility()
{
}
public static void CopyStream(System.IO.Stream input, System.IO.Stream output)
{
byte[] buffer = new byte[2000];
int len;
while ((len = input.Read(buffer, 0, 2000)) > 0)
{
output.Write(buffer, 0, len);
}
output.Flush();
}
public void compressFile(string inFile, string outFile)
{
System.IO.FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create);
zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFileStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION);
System.IO.FileStream inFileStream = new System.IO.FileStream(inFile, System.IO.FileMode.Open);
try
{
CopyStream(inFileStream, outZStream);
}
finally
{
outZStream.Close();
outFileStream.Close();
inFileStream.Close();
}
}
public void uncompressFile(string inFile, string outFile)
{
int data = 0;
int stopByte = -1;
System.IO.FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create);
zlib.ZInputStream inZStream = new zlib.ZInputStream(System.IO.File.Open(inFile, System.IO.FileMode.Open, System.IO.FileAccess.Read));
while (stopByte != (data = inZStream.Read()))
{
byte _dataByte = (byte)data;
outFileStream.WriteByte(_dataByte);
}
inZStream.Close();
outFileStream.Close();
}
}
Guarda il codice di esempio più da vicino, sta copiando i dati da un normale Filestream a ZOutputStream. La decompressione deve avvenire attraverso quel livello.
private void decompressFile(string inFile, string outFile)
{
System.IO.FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create);
zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFileStream);
System.IO.FileStream inFileStream = new System.IO.FileStream(inFile, System.IO.FileMode.Open);
try
{
CopyStream(inFileStream, outZStream);
}
finally
{
outZStream.Close();
outFileStream.Close();
inFileStream.Close();
}
}
Di recente ho avuto la sfortuna di distribuire documenti precedentemente usati da php su una varietà di browser e piattaforme tra cui IE7. Una volta ho capito che i documenti erano zlib e non gzip (come si pensava all'epoca) ho usato SharpZipLib nel modo seguente in .NET Framework v4 (sfruttando Stream.CopyTo ):
public static byte[] DecompressZlib(Stream source)
{
byte[] result = null;
using (MemoryStream outStream = new MemoryStream())
{
using (InflaterInputStream inf = new InflaterInputStream(source))
{
inf.CopyTo(outStream);
}
result = outStream.ToArray();
}
return result;
}
Pensavo di metterlo qui nel caso qualcuno avesse bisogno di aiuto con le classi da usare da SharpZipLib.