zlib da C ++ a C # (Come convertire byte [] per lo streaming ed effettuare lo streaming di byte [])

StackOverflow https://stackoverflow.com/questions/737258

  •  09-09-2019
  •  | 
  •  

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?

È stato utile?

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)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top