6

我的任务是使用 zlib 解压缩数据包(收到),然后使用算法从数据中制作图片

好消息是我有 C++ 代码,但任务是用 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;
            }
        }

我正在尝试使用 zlib.NET 执行此操作,但所有演示都有要解压缩的代码(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();
    }

我的问题:我不想在解压后保存文件,因为我必须使用 C++ 代码中显示的算法。

如何将 byte[] 数组转换为类似于 C# zlib 代码中的流以解压缩数据,然后如何将流转换回字节数组?

另外,如何将 zlib.NET 代码更改为不保存文件?

4

2 回答 2

10

只需使用 MemoryStreams 而不是 FileStreams:

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

然后你可以使用output.ToArray()之后得到一个字节数组。

请注意,通常最好使用using语句而不是单个 try/finally 块 - 否则如果第一次调用Close失败,则不会进行其余的调用。你可以像这样嵌套它们:

using (MemoryStream output = new MemoryStream())
using (Stream outZStream = new zlib.ZOutputStream(output))
using (Stream input = new MemoryStream(bytes))
{
    CopyStream(inFileStream, outZStream);
    return output.ToArray();
}
于 2009-04-10T10:34:34.490 回答
6

我刚刚遇到了同样的问题。

为了完整性......(因为这让我难过了几个小时)

对于 ZLib.Net,在调用 return output.ToArray() 之前,您还必须调用 finish(),这通常发生在 Close() 期间

否则,您将从内存流中获得一个空/不完整的字节数组,因为 ZStream 实际上还没有写入所有数据:

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

在此示例中,我还使用了 zlib 命名空间:

using zlib;

最初在这个线程中找到: ZLib解压

我还没有足够的积分来投票,所以...

感谢 Tim Greaves 关于 ToArray 之前完成的提示

和 Jon Skeet 关于嵌套流的 using 语句的提示(我比 try/finally 更喜欢它)

于 2010-10-02T03:25:46.527 回答