تعطي بيانات المصدر وإزالة ضغطها نتيجة مختلفة عن بيانات المصدر

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

  •  27-09-2019
  •  | 
  •  

سؤال

في تطبيقي ، أحتاج إلى إلغاء ضغط البيانات التي كتبها DataContractSerializer لضغط الدفق في تطبيق آخر ، وتحرير البيانات المضغوطة وضغطها مرة أخرى.

إزالة الضغط يعمل بشكل جيد ، ولكن ليس للبيانات المضغوطة من قبلي.

المشكلة هي أنه عندما أفعل هذا: byte [] result = sembressor.compress (compressor.decussive (sourcedata)) ؛

يختلف طول صفيف البايت الناتج عن صفيف Sourcedata.

علي سبيل المثال:

    string source = "test value";
    byte[] oryg = Encoding.Default.GetBytes(source);

    byte[] comp = Compressor.Compress(oryg);
    byte[] result1 = Compressor.Decompress(comp);

    string result2 = Encoding.Default.GetString(res);

وهنا النتيجة.

هنا هو رمز فئة الضاغط الخاصة بي.

public static class Compressor
{
    public static byte[] Decompress(byte[] data)
    {
        byte[] result;

        using (MemoryStream baseStream = new MemoryStream(data))
        {
            using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Decompress))
            {
                result = ReadFully(stream, -1);
            }
        }

        return result;
    }

    public static byte[] Compress(byte[] data)
    {
        byte[] result;

        using (MemoryStream baseStream = new MemoryStream())
        {
            using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Compress, true))
            {
                stream.Write(data, 0, data.Length);
                result = baseStream.ToArray();
            }
        }

        return result;
    }

    /// <summary>
    /// Reads data from a stream until the end is reached. The
    /// data is returned as a byte array. An IOException is
    /// thrown if any of the underlying IO calls fail.
    /// </summary>
    /// <param name="stream">The stream to read data from</param>
    /// <param name="initialLength">The initial buffer length</param>
    private static byte[] ReadFully(Stream stream, int initialLength)
    {
        // If we've been passed an unhelpful initial length, just
        // use 32K.
        if (initialLength < 1)
        {
            initialLength = 65768 / 2;
        }

        byte[] buffer = new byte[initialLength];
        int read = 0;

        int chunk;
        while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
        {
            read += chunk;

            // If we've reached the end of our buffer, check to see if there's
            // any more information
            if (read == buffer.Length)
            {
                int nextByte = stream.ReadByte();

                // End of stream? If so, we're done
                if (nextByte == -1)
                {
                    return buffer;
                }

                // Nope. Resize the buffer, put in the byte we've just
                // read, and continue
                byte[] newBuffer = new byte[buffer.Length * 2];
                Array.Copy(buffer, newBuffer, buffer.Length);
                newBuffer[read] = (byte)nextByte;
                buffer = newBuffer;
                read++;
            }
        }
        // Buffer is now too big. Shrink it.
        byte[] ret = new byte[read];
        Array.Copy(buffer, ret, read);
        return ret;
    }
}

الرجاء مساعدتي في هذه الحالة إذا استطعت. مع أطيب التحيات ، آدم

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

المحلول

(تم تحريره: تم تحويله من استخدام Flush ، والذي قد لا يزال قد لا يطرد جميع البايتات ، لضمان التخلص من المنحنى أولاً ، وفقًا لإجابة Phil هنا: zip و unsip string مع انحراف)

قبل محاولة القراءة من المتجر الداعم ، يجب عليك التأكد من أن دفق المنافذ قد تم مسح نفسه بالكامل عند الضغط ، مما يسمح للفرغ بإنهاء الضغط وكتابة البايتات النهائية. إن إغلاق البخار المنهك ، أو التخلص منه ، سيحقق ذلك.

public static byte[] Compress(byte[] data)
{
    byte[] result;

    using (MemoryStream baseStream = new MemoryStream())
    {
        using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Compress, true))
        {
            stream.Write(data, 0, data.Length);
        }
        result = baseStream.ToArray();  // only safe to read after deflate closed
    }

    return result;
}    

كما تبدو روتينك بشكل لا يصدق معقدًا بشكل لا يصدق ومن المحتمل أن يكون لديك أخطاء. كائن واحد:

while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)

عند قراءة الجزء الثاني ، read سيكون أكبر من طول المخزن المؤقت ، مما يعني أنه سيمر دائمًا قيمة سالبة للتيار. اقرأ عدد البايتات التي يجب قراءتها. أظن أنه لن يقرأ أبدًا الجزء الثاني ، ويعود الصفر ، ويسقط من الحلقة.

أوصي نسخة جون من قرب لهذا الغرض: إنشاء مجموعة بايت من دفق

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