Tôi đang giao tiếp với máy chủ yêu cầu dữ liệu được gửi đến đó được nén với Làm lệch hướng thuật toán (Huffman encoding + LZ77) và cũng gửi dữ liệu mà tôi cần đến Inflate.Python: Thổi phồng và làm lệch triển khai
Tôi biết rằng Python bao gồm Zlib, và rằng các thư viện C trong zlib cuộc gọi hỗ trợ để Bơm và Deflate, nhưng những hình như không được cung cấp bởi module Python zlib. Nó cung cấp Compress và Decompress, nhưng khi tôi thực hiện cuộc gọi như sau:
result_data = zlib.decompress(base64_decoded_compressed_string)
tôi nhận được lỗi sau:
Error -3 while decompressing data: incorrect header check
Gzip làm không tốt; khi thực hiện cuộc gọi như:
result_data = gzip.GzipFile(fileobj = StringIO.StringIO(base64_decoded_compressed_string)).read()
tôi nhận được lỗi:
IOError: Not a gzipped file
mà làm cho cảm giác như là dữ liệu là một xì hơi tập tin không phải là một sự thật Gzipped tập tin.
Bây giờ tôi biết rằng có Làm lệch hoạt động sẵn có (Pyflate), nhưng tôi không biết về việc triển khai Inflate.
Dường như có một vài lựa chọn:
- Tìm một thực hiện có (lý tưởng) của Bơm và Deflate bằng Python
- Viết phần mở rộng Python của riêng tôi với zlib c thư viện bao gồm Thổi phồng và Làm lệch
- Gọi một thứ khác có thể là được thực hiện từ dòng lệnh (chẳng hạn như tập lệnh Ruby, kể từ Thổi phồng/Làm lệch cuộc gọi trong zlib được gói đầy đủ trong Ruby)
- ?
Tôi đang tìm kiếm giải pháp, nhưng thiếu giải pháp tôi sẽ biết ơn vì thông tin chi tiết, ý kiến xây dựng và ý tưởng.
thông tin bổ sung: Kết quả của việc xì hơi (và mã hóa) một chuỗi nên, cho các mục đích tôi cần, cung cấp cho các kết quả tương tự như đoạn sau đây của mã C#, nơi mà các tham số đầu vào là một mảng byte UTF tương ứng với dữ liệu cần nén:
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;
}
Chạy ứng dụng này.NET mã cho chuỗi "deflate và mã hóa tôi" cho kết quả
7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iZvl5mbV5mi1nab6cVrM8XeT/Dw==
Khi "deflate và mã hóa cho tôi" được chạy qua Python Zlib.compress() và sau đó mã hóa base64, kết quả là "eJxLSU3LSSxJVUjMS1FIzUvOT0lVyE0FAFXHB6k =" .
Rõ ràng là zlib.compress() không phải là việc triển khai cùng một thuật toán với thuật toán Deflate chuẩn.
biết thêm thông tin:
2 byte đầu tiên của NET deflate dữ liệu ("7b0HY ..."), sau khi giải mã b64 là 0xEDBD, mà không tương ứng với dữ liệu Gzip (0x1f8b), BZip2 (0x425A) dữ liệu hoặc dữ liệu Zlib (0x789C).
2 byte đầu tiên của dữ liệu được nén Python ("eJxLS ..."), sau khi giải mã b64 là 0x789C. Đây là tiêu đề Zlib.
SOLVED
Để xử lý các deflate liệu và thổi phồng, không header và tổng kiểm tra, những điều sau đây cần thiết để xảy ra:
On deflate/nén: dải hai byte đầu tiên (header) và bốn byte cuối cùng (tổng kiểm tra).
Khi thổi phồng/giải nén: có đối số thứ hai cho kích thước cửa sổ. Nếu giá trị này là âm, nó sẽ chặn tiêu đề. đây là phương pháp của tôi hiện nay, bao gồm cả mã hóa base64/giải mã - và hoạt động bình thường:
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)
+1 Cảm ơn thông tin bổ sung. – Demi
@ John Machin: Để trả lời quan sát đầu tiên của bạn ... kết quả chỉ dài hơn trong trường hợp các chuỗi ngắn hơn (header? Padding?). Khi tôi ăn trong 161 byte dữ liệu để giảm phát, trước khi mã hóa base64 kết quả là 126 byte. – Demi
@ John Machin: Thông tin chi tiết và thông tin tuyệt vời. Chữ ký Java của deflater được sử dụng là chữ cái có hai tham số, với nowrap == true. Tôi đã sử dụng ví dụ deflater một dòng của bạn và nó thổi phồng tốt trong .NET và Java, mặc dù có vẻ khác so với giá trị được tạo ra bởi deflating với các thư viện trong các ngôn ngữ đó. Điều đó thật tuyệt. Bây giờ tôi đang làm việc trên thổi phồng - lấy dữ liệu xì hơi được tạo ra bởi Java hoặc .NET và thêm vào một adler32 checksum và tiêu đề zlib để xem liệu tôi có thể lấy Python để tiêu thụ nó tốt hay không. Tôi sẽ cho bạn biết làm thế nào nó đi. – Demi