2009-04-10 41 views
6

Il mio compito è decomprimere un pacchetto (ricevuto) usando zlib e quindi usare un algoritmo per fare una foto dai datizlib da C++ a C# (Come convertire byte [] in stream e stream in byte [])

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 avere quel codice per 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 mostrato nel codice C++.

Come convertire l'array byte [] in un flusso simile a quello nel codice zlib C# per decomprimere i dati e come convertire il flusso in array di byte?

Inoltre, come modificare il codice zlib.NET per NON salvare i file?

+0

necessario esattamente lo stesso. Grazie! – lesderid

+0

Voglio dare una taglia a @JoshStribling - Posso farlo domani. –

risposta

10

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.

Nota che in genere è preferibile utilizzare le istruzioni using anziché un singolo tentativo/ultimo blocco, altrimenti se la prima chiamata a Close non riesce, il resto non verrà eseguito. È possibile nidificarli 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(); 
} 
+1

Jon Skeet, ammiro il libro che hai scritto (C# in profondità). Ne scriverai un altro quando uscirà C# v4? –

+1

Non c'è nulla di assolutamente concreto, ma spero di scrivere una seconda edizione di C# in Depth per coprire il C# 4, sì. Sono contento che ti sia piaciuta la prima edizione :) –

5

Mi sono imbattuto in questo stesso problema.

per completezza ... (dal momento che questo mi ha messo in difficoltà per diverse ore)

Nel caso di ZLib.Net si hanno anche per chiamare finitura(), che di solito accade durante Close(), prima di chiamare il ritorno 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 i' m utilizzando anche lo spazio dei nomi zlib:

using zlib; 

Originariamente trovato in questa discussione: ZLib decompression

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)

+0

Grazie mille! Questo è un suggerimento fantastico! –

+0

cosa sono inData e fuoriData qui ??? – pulkit