سؤال

أنا أتماشى مع خادم يتطلب أن يتم ضغط البيانات المرسلة إليها فرط الخوارزمية (هوفمان تشفير + LZ77) ويرسل أيضا البيانات التي أحتاج إليها تضخم.

أعلم أن بيثون يشمل ZLIB، وأن مكتبات C في دعم دعم ZLIB تضخم و فرط, ، ولكن يبدو أن هذه على ما يبدو لا توفرها وحدة بيثون ZLIB. انها تقدم ضغط و إلغاء ضغط, ، ولكن عندما أقوم بإجراء مكالمة مثل ما يلي:

result_data = zlib.decompress( base64_decoded_compressed_string )

أتلقى الخطأ التالي:

Error -3 while decompressing data: incorrect header check

gzip لا أفضل؛ عند إجراء مكالمة مثل:

result_data = gzip.GzipFile( fileobj = StringIO.StringIO( base64_decoded_compressed_string ) ).read()

أتلقى الخطأ:

IOError: Not a gzipped file

مما يجعل المنطقي مثل البيانات انخفض ملف ليس صحيحا gzpeced. ملف.

الآن أعرف أن هناك فرط التنفيذ المتاح (Pyflate)، لكنني لا أعرف تضخم تطبيق.

يبدو أن هناك بعض الخيارات:

  1. العثور على تنفيذ موجود (مثالي) من تضخم و فرط في بيثون
  2. اكتب امتداد بيثون الخاص بي إلى مكتبة Zlib C التي تتضمن تضخم و فرط
  3. اتصل بشيء آخر يمكن تنفيذه من سطر الأوامر (مثل البرنامج النصي Ruby، منذ تضخم/فرط المكالمات في ZLIB ملفوفة بالكامل في روبي)
  4. ?

أسعى إلى حل، ولكن تفتقر إلى حل سأكون شاكرا للرؤى والآراء البناءة والأفكار.

معلومة اضافية: نتيجة التراجع (والترميز) سلسلة ينبغي، لأغراض أحتاجها، أعط نفس النتيجة مثل مقتطف رمز C # التالي، حيث تعتبر المعلمة الإدخال مجموعة من بايت UTF المقابلة للبيانات لضغط:

public static string DeflateAndEncodeBase64(byte[] data)
{
    if (null == data || data.Length < 1) return null;
    string compressedBase64 = "";

    //write into a new memory stream wrapped by a deflate stream
    using (MemoryStream ms = new MemoryStream())
    {
        using (DeflateStream deflateStream = new DeflateStream(ms, CompressionMode.Compress, true))
        {
            //write byte buffer into memorystream
            deflateStream.Write(data, 0, data.Length);
            deflateStream.Close();

            //rewind memory stream and write to base 64 string
            byte[] compressedBytes = new byte[ms.Length];
            ms.Seek(0, SeekOrigin.Begin);
            ms.Read(compressedBytes, 0, (int)ms.Length);
            compressedBase64 = Convert.ToBase64String(compressedBytes);
        }
    }
    return compressedBase64;
}

تشغيل رمز .NET هذا لسلسلة "تحريف وترمزني" يعطي النتيجة

7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iZvl5mbV5mi1nab6cVrM8XeT/Dw==

عند تشغيل "تحريف وتشفيرني" من خلال Python Zlib.compress () ثم Base64 المشفرة، والنتيجة هي "ejxlsu3lsxxjvujms1fizuvot0lvye0fafxhb6k =".

من الواضح أن zlib.compress () ليس تطبيقا لنفس الخوارزمية مثل خوارزمية الانفصال القياسية.

معلومات اكثر:

أول 2 بايت من بيانات .NET DESLATE ("7B0HY ...")، بعد فك التشفير B64 هي 0xedbd، والتي لا تتوافق مع بيانات Gzip (0x1f8b)، بيانات bzip2 (0x425a)، أو بيانات zlib (0x789c).

أول 2 بايت من البيانات المضغوطة بيثون ("ejxls ...")، بعد فك شفرة B64 هي 0x789c. هذا هو رأس ZLIB.

تم حلها

للتعامل مع تكديس RAW وتضخيمها، بدون رأس وميكشر، فإن الأمور التالية اللازمة تحدث:

عند الانفصال / ضغط: قم بقطاع أول اثنين بايت (رأس) والبايت الأربعة الأخيرة (المجموع الاختباري).

على تضخيم / إلغاء الضغط: هناك حجة ثانية لحجم النافذة. إذا كانت هذه القيمة سلبية، فإنها تقمع الرؤوس. فيما يلي أساليبي حاليا، بما في ذلك ترميز / فك تشفير الأساس 64 - وتعمل بشكل صحيح:

import zlib
import base64

def decode_base64_and_inflate( b64string ):
    decoded_data = base64.b64decode( b64string )
    return zlib.decompress( decoded_data , -15)

def deflate_and_base64_encode( string_val ):
    zlibbed_str = zlib.compress( string_val )
    compressed_string = zlibbed_str[2:-4]
    return base64.b64encode( compressed_string )
هل كانت مفيدة؟

المحلول

هذه هي وظيفة إضافية لإجابة Mizardx، مما يمنح بعض التفسيرات والخلفية.

يرى http://www.chiramattel.com/george/Blog/Blog/2007/09/09/deflatestream-block-length-lengh-not-match.html.

وفق RFC 1950., ، يتكون مجرى ZLIB المشيد بالطريقة الافتراضية من:

  • رأس 2 بايت (مثل 0x78 0x9c)
  • تيار الانفصال - انظر RFC 1951.
  • الاختباري ADLER-32 من البيانات غير المضغوطة (4 بايت)

ج # DeflateStream يعمل على (خمنت ذلك) تيار ينفدي. يخبر رمز Mizardx وحدة ZLIB أن البيانات هي دفق Dyplate RAW.

الملاحظات: (1) يأمل المرء الأسلوب C # "الانكماش" الذي ينتج عنه سلسلة أطول يحدث فقط مع إدخال قصير (2) باستخدام تدفق دفق RAW دون الاختباري ADLER-32؟ محفوف بالمخاطر قليلا، ما لم يتم استبدال شيء أفضل.

تحديثات

رسالة خطأ Block length does not match with its complement

إذا كنت تحاول تضخيم بعض البيانات المضغوطة مع C # DeflateStream وتحصل على هذه الرسالة، فمن الممكن تماما أن تعطيه دفق AA ZLIB، وليس دفقا ينفث.

يرى كيف يمكنك استخدام deflatestream على جزء من ملف؟

قم أيضا بنسخ / لصق رسالة الخطأ في بحث Google وستحصل على العديد من الزيارات (بما في ذلك الواحد مقدمة هذه الإجابة) تقول الكثير من الشيء.

جاوة Deflater ... المستخدمة من قبل "موقع الويب" ... C # deflatestream "واضح جدا واختبارها ضد تنفيذ جافا". أي من منشئين Java Deflater المحتمل التالي هو الموقع الإلكتروني باستخدام؟

public Deflater(int level, boolean nowrap)

ينشئ ضاغط جديد باستخدام مستوى الضغط المحدد. إذا كان "NewRAP" صحيحا، فلن يتم استخدام حقول رأس ZLIB و CheckSum من أجل دعم تنسيق الضغط المستخدم في كل من GZIP و PKZIP.

public Deflater(int level)

ينشئ ضاغط جديد باستخدام مستوى الضغط المحدد. سيتم إنشاء البيانات المضغوطة بتنسيق ZLIB.

public Deflater()

ينشئ ضاغط جديد مع مستوى الضغط الافتراضي. سيتم إنشاء البيانات المضغوطة بتنسيق ZLIB.

دفعة واحدة مغلوطة بعد إلقاء رأس 2 بايت Zlib Checksum 4 بايت:

uncompressed_string.encode('zlib')[2:-4] # does not work in Python 3.x

أو

zlib.compress(uncompressed_string)[2:-4]

نصائح أخرى

لا يزال بإمكانك استخدام zlib الوحدة النمطية لتضخيم / تحريف البيانات. ال gzip تستخدم الوحدة النمطية داخليا، ولكنها تضيف رأس ملف لجعله في ملف Gzip. أنظر إلى gzip.py ملف، شيء مثل هذا يمكن أن يعمل:

import zlib

def deflate(data, compresslevel=9):
    compress = zlib.compressobj(
            compresslevel,        # level: 0-9
            zlib.DEFLATED,        # method: must be DEFLATED
            -zlib.MAX_WBITS,      # window size in bits:
                                  #   -15..-8: negate, suppress header
                                  #   8..15: normal
                                  #   16..30: subtract 16, gzip header
            zlib.DEF_MEM_LEVEL,   # mem level: 1..8/9
            0                     # strategy:
                                  #   0 = Z_DEFAULT_STRATEGY
                                  #   1 = Z_FILTERED
                                  #   2 = Z_HUFFMAN_ONLY
                                  #   3 = Z_RLE
                                  #   4 = Z_FIXED
    )
    deflated = compress.compress(data)
    deflated += compress.flush()
    return deflated

def inflate(data):
    decompress = zlib.decompressobj(
            -zlib.MAX_WBITS  # see above
    )
    inflated = decompress.decompress(data)
    inflated += decompress.flush()
    return inflated

لا أعرف إذا كان هذا يتوافق تماما مع ما يتطلبه الخادم الخاص بك، لكن هاتين الوظيفتين قادران على رحلة جولة أي بيانات حاولت بها.

خرائط المعلمات مباشرة إلى ما يتم تمريره إلى وظائف مكتبة ZLIB.

بيثونجيم
zlib.compressobj(...)deflateInit(...)
compressobj.compress(...)deflate(...)
zlib.decompressobj(...)inflateInit(...)
decompressobj.decompress(...)inflate(...)

يقوم المنشئون بإنشاء الهيكل وملء القيم الافتراضية، وتمريرها إلى وظائف Init. ال compress/decompress طرق تحديث الهيكل وتمريرها إلى inflate/deflate.

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