zlib 从 C++ 到 C#(如何将 byte[] 转换为流和流到 byte[])

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/737258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 23:13:37  来源:igfitidea点击:

zlib from C++ to C#(How to convert byte[] to stream and stream to byte[])

c#bytezlib

提问by Ivan Prodanov

My task is to decompress a packet(received) using zlib and then use an algoritm to make a picture from the data

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

The good news is that I have the code in C++,but the task is to do it in C#

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

I'm trying to do this with zlib.NET ,but all demos have that code to decompress(C#)

我正在尝试使用 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();
    }

My problem:I don't want to save the file after decompression,because I have to use the algoritm shown in the C++ code.

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

How to convert the byte[] array into a stream similiar to the one in the C# zlib code to decompress the data and then how to convert the stream back into byte array?

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

Also,How to change the zlib.NET code to NOT save files?

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

采纳答案by Jon Skeet

Just use MemoryStreams instead of FileStreams:

只需使用 MemoryStreams 而不是 FileStreams:

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

Then you can use output.ToArray()afterwards to get a byte array out.

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

Note that it's generally better to use usingstatements instead of a single try/finally block - as otherwise if the first call to Closefails, the rest won't be made. You can nest them like this:

请注意,通常最好使用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();
}

回答by Josh Stribling

I just ran into this same issue.

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

For Completeness... (since this stumped me for several hours)

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

In the case of ZLib.Net you also have to call finish(), which usually happens during Close(), before you call return output.ToArray()

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

Otherwise you will get an empty/incomplete byte array from your memory stream, because the ZStream hasn't actually written all of the data yet:

否则你会从你的内存流中得到一个空的/不完整的字节数组,因为 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();
    }
}

In this example I'm also using the zlib namespace:

在这个例子中,我还使用了 zlib 命名空间:

using zlib;

Originally found in this thread: ZLib decompression

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

I don't have enough points to vote up yet, so...

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

Thanks to Tim Greaves for the tip regarding finish before ToArray

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

And Jon Skeet for the tip regarding nesting the using statements for streams (which I like much better than try/finally)

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