zlib da C ++ a C # (Come convertire byte [] per lo streaming ed effettuare lo streaming di byte [])
Domanda
Il mio compito è quello di decomprimere un pacchetto (ricevuto) usando zlib e quindi utilizzare un algoritmo per fare una foto dai dati
La buona notizia è che ho il codice in C ++, ma il compito è quello di farlo in C #
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;
}
}
che sto cercando di fare questo con zlib.NET, ma tutte le demo hanno quel codice decomprimere (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();
}
Il mio problema: non voglio salvare il file dopo la decompressione, perché devo usare l'algoritmo illustrato nel codice C ++
.Come convertire la matrice di byte [] in un simile flusso a quello nel codice C # zlib per decomprimere i dati e poi come convertire il flusso di nuovo in array di byte?
Inoltre, Come cambiare il codice zlib.NET per non salvare i file?
Soluzione
Basta usare MemoryStreams invece di filestreams:
// Assuming inputData is a byte[]
MemoryStream input = new MemoryStream(inputData);
MemoryStream output = new MemoryStream();
Quindi è possibile utilizzare output.ToArray()
in seguito per ottenere un array di byte fuori.
Si noti che è generalmente meglio usare le dichiarazioni using
invece di un singolo try / finally blocca - come altrimenti se la prima chiamata a Close
non riesce, non sarà reso il resto. È possibile nido loro in questo modo:
using (MemoryStream output = new MemoryStream())
using (Stream outZStream = new zlib.ZOutputStream(output))
using (Stream input = new MemoryStream(bytes))
{
CopyStream(inFileStream, outZStream);
return output.ToArray();
}
Altri suggerimenti
Ho appena incontrato lo stesso problema.
Per completezza ... (dal momento che questo mi ha sconcertato per diverse ore)
Nel caso di ZLib.Net si hanno anche per chiamare finitura (), che di solito accade durante Close (), prima di chiamare tornare output.ToArray ()
In caso contrario si otterrà un array vuoto / incompleto di byte dal flusso di memoria, perché lo zStream non ha effettivamente scritto tutti i dati ancora:
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 questo esempio Sto anche utilizzando lo spazio zlib:
using zlib;
In origine si trovano in questa discussione: ZLib decompressione
Non ho abbastanza punti per votare ancora, quindi ...
Grazie a Tim Greaves per la punta per quanto riguarda traguardo prima ToArray
E Jon Skeet per la punta per quanto riguarda la nidificazione le istruzioni using per i flussi (che mi piace molto meglio di try / finally)