zlib de C ++ para C # (Como converter byte [] para transmitir e fluxo de byte [])

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

  •  09-09-2019
  •  | 
  •  

Pergunta

A minha tarefa é para descomprimir um pacote (recebido) usando zlib e, em seguida, usar um algoritmo para fazer uma imagem a partir dos dados

A boa notícia é que eu tenho o código em C ++, mas a tarefa é fazê-lo em 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;
            }
        }

Eu estou tentando fazer isso com zlib.NET, mas todos demos ter esse código para descomprimir (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();
    }

Meu problema:. Eu não quero salvar o arquivo após a descompressão, porque eu tenho que usar o algoritmo mostrado no código C ++

Como converter a matriz byte [] em um similiar fluxo para o um no código C # zlib para descomprimir os dados e como converter as costas fluxo em array de bytes?

Além disso, Como alterar o código zlib.NET para não salvar arquivos?

Foi útil?

Solução

Basta usar MemoryStreams em vez de FileStreams:

// Assuming inputData is a byte[]
MemoryStream input = new MemoryStream(inputData);
MemoryStream output = new MemoryStream();

Então você pode usar output.ToArray() depois de obter uma matriz de bytes para fora.

Note que é geralmente melhor declarações uso using em vez de um único try / finally bloquear - caso contrário, se a primeira chamada para Close falhar, o resto não será feita. Você pode aninhar-los como este:

using (MemoryStream output = new MemoryStream())
using (Stream outZStream = new zlib.ZOutputStream(output))
using (Stream input = new MemoryStream(bytes))
{
    CopyStream(inFileStream, outZStream);
    return output.ToArray();
}

Outras dicas

Eu apenas corri para este mesmo problema.

Para completar ... (uma vez que este me perplexo por várias horas)

No caso de ZLib.Net você também tem que terminar call (), o que geralmente acontece durante Close (), antes de chamar voltar output.ToArray ()

Caso contrário, você vai ter uma matriz de bytes vazia / incompleta do seu fluxo de memória, porque o zStream não tenha realmente escrito todos os dados ainda:

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();
    }
}

Neste exemplo, eu também estou usando o namespace zlib:

using zlib;

Originalmente encontrado neste tópico: ZLib descompressão

Eu não tenho pontos suficientes para votar-se ainda, então ...

Graças à Tim Greaves pela dica a respeito de chegada antes ToArray

E Jon Skeet pela dica sobre nidificação os usando instruções para fluxos (que eu gosto muito melhor do que try / finally)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top