ZLIB من C ++ إلى C # (كيفية تحويل البايت [] إلى الدفق والدفق إلى البايت [])

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

  •  09-09-2019
  •  | 
  •  

سؤال

مهمتي هي إلغاء ضغط الحزمة (المستلمة) باستخدام Zlib ثم استخدم Glgoritm لإجراء صورة من البيانات

والخبر السار هو أن لدي رمز في 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();
    }

مشكلتي: لا أريد حفظ الملف بعد إلغاء الضغط، لأنني لا بد لي من استخدام Algoritm الموضح في رمز C ++.

كيفية تحويل صفيف البايت [] إلى دفق متشابه إلى واحد في رمز C # ZLIB لإلغاء ضغط البيانات ثم كيفية تحويل الدفق مرة أخرى إلى صفيف بايت؟

أيضا، كيفية تغيير رمز Zlib.net لعدم حفظ الملفات؟

هل كانت مفيدة؟

المحلول

ما عليك سوى استخدام مخصصات بدلا من FileStreams:

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

ثم يمكنك استخدام output.ToArray() بعد ذلك للحصول على صفيف بايت خارج.

لاحظ أنه من الأفضل بشكل عام الاستخدام using البيانات بدلا من تجربة واحدة / كتلة أخيرا - كما خلاف ذلك إذا كانت الدعوة الأولى إلى 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();
}

نصائح أخرى

لقد ركضت فقط في هذه المشكلة نفسها.

للكمال ... (لأن هذا كذبني لعدة ساعات)

في حالة Zlib.net، يجب عليك أيضا الاتصال بالإنهاء ()، والتي تحدث عادة أثناء الإغلاق ()، قبل أن تتصل بإخراج الإرجاع.

وإلا فستحصل على صفيف بايت فارغ / غير مكتمل من دفق الذاكرة، لأن 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 decumpression

ليس لدي نقاط كافية للتصويت حتى الآن، لذلك ...

بفضل تيم Greaves for the Tip فيما يتعلق بالانتهاء قبل التوارد

و JON SKEET للحصول على طرف فيما يتعلق بالتعشيش البيانات باستخدام التدفقات (التي أحبها أفضل بكثير من المحاولة / أخيرا)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top