zlib von C ++ auf C # (Wie byte [] konvertieren zu streamen und [] Byte-Stream)
Frage
Meine Aufgabe ist es, ein Paket (erhalten) mit zlib zu dekomprimieren und dann einen algoritm verwenden, um ein Bild aus den Daten zu machen
Die gute Nachricht ist, dass ich den Code in C ++, aber die Aufgabe ist es in C # zu tun
C ++
//Read the first values of the packet received
DWORD image[200 * 64] = {0}; //used for algoritm(width always = 200 and height always == 64)
int imgIndex = 0; //used for algoritm
unsigned char rawbytes_[131072] = {0}; //read below
unsigned char * rawbytes = rawbytes_; //destrination parameter for decompression(ptr)
compressed = r.Read<WORD>(); //the length of the compressed bytes(picture)
uncompressed = r.Read<WORD>(); //the length that should be after decompression
width = r.Read<WORD>(); //the width of the picture
height = r.Read<WORD>(); //the height of the picture
LPBYTE ptr = r.GetCurrentStream(); //the bytes(file that must be decompressed)
outLen = uncompressed; //copy the len into another variable
//Decompress
if(uncompress((Bytef*)rawbytes, &outLen, ptr, compressed) != Z_OK)
{
printf("Could not uncompress the image code.\n");
Disconnect();
return;
}
//Algoritm to make up the picture
// Loop through the data
for(int c = 0; c < (int)height; ++c)
{
for(int r = 0; r < (int)width; ++r)
{
imgIndex = (height - 1 - c) * width + r;
image[imgIndex] = 0xFF000000;
if(-((1 << (0xFF & (r & 0x80000007))) & rawbytes[((c * width + r) >> 3)]))
image[imgIndex] = 0xFFFFFFFF;
}
}
Ich versuche, dies mit zlib.NET zu tun, aber alle Demos haben diesen Code zu dekomprimieren (C #)
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();
}
}
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();
}
Mein Problem: Ich mag nicht, um die Datei nach der Dekomprimierung speichern, weil ich die algoritm in dem C ++ Code gezeigt verwenden
.Wie die byte [] Array in einen Strom ähnlich den in dem C # zlib-Code konvertieren, die Daten zu dekomprimieren und dann, wie der Strom wieder in Byte-Array zu konvertieren?
Auch, wie der zlib.NET Code ändern Dateien nicht speichern?
Lösung
Verwenden Sie einfach MemoryStreams statt Filestreams:
// Assuming inputData is a byte[]
MemoryStream input = new MemoryStream(inputData);
MemoryStream output = new MemoryStream();
Dann können Sie output.ToArray()
verwenden danach ein Byte-Array, um aus.
Beachten Sie, dass es in der Regel besser zu using
Aussagen anstelle eines einzigen try / finally-Block zu verwenden - wie sonst, wenn der erste Aufruf von Close
ausfällt, wird der Rest nicht vorgenommen werden. Sie können Nest sie wie folgt:
using (MemoryStream output = new MemoryStream())
using (Stream outZStream = new zlib.ZOutputStream(output))
using (Stream input = new MemoryStream(bytes))
{
CopyStream(inFileStream, outZStream);
return output.ToArray();
}
Andere Tipps
Ich lief in das gleiche Problem.
Für Vollständigkeits ... (da dies stapfte mich für mehrere Stunden)
Im Fall von ZLib.Net Sie auch beenden nennen haben (), die in der Regel während des Schließens geschieht (), bevor Sie zurück output.ToArray nennen ()
Andernfalls werden Sie einen leeren / unvollständigen Byte-Array von dem Speicherstrom erhalten, weil die zStream nicht tatsächlich alle Daten geschrieben noch:
public static void CompressData(byte[] inData, out byte[] outData)
{
using (MemoryStream outMemoryStream = new MemoryStream())
using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream, zlibConst.Z_DEFAULT_COMPRESSION))
using (Stream inMemoryStream = new MemoryStream(inData))
{
CopyStream(inMemoryStream, outZStream);
outZStream.finish();
outData = outMemoryStream.ToArray();
}
}
public static void DecompressData(byte[] inData, out byte[] outData)
{
using (MemoryStream outMemoryStream = new MemoryStream())
using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream))
using (Stream inMemoryStream = new MemoryStream(inData))
{
CopyStream(inMemoryStream, outZStream);
outZStream.finish();
outData = outMemoryStream.ToArray();
}
}
In diesem Beispiel verwende ich auch den zlib-Namespace:
using zlib;
Ursprünglich in diesem Thread gefunden: ZLib Dekompression
Ich habe nicht genug Punkte noch stimmen, also ...
Dank Tim Greaves für die Spitze vor ToArray bezüglich Finish
Und Jon Skeet für die Spitze in Bezug auf die Verwendung von Aussagen für Ströme nisten (was ich viel besser gefällt als try / finally)