मैं एक स्क्रिप्ट लिख रहा हूं जो gzip धाराओं के रूप में उपकरण से आने वाले डेटा के साथ काम करेगा। लगभग 9 0% मामलों में, gzip
मॉड्यूल पूरी तरह से काम करता है, लेकिन कुछ धाराएं इसे IOError: Not a gzipped file
उत्पन्न करती हैं। यदि gzip हेडर हटा दिया गया है और डिफ्लेट स्ट्रीम सीधे zlib
पर खिलाया गया है, तो मुझे इसके बजाय Error -3 while decompressing data: incorrect header check
मिलता है। दीवार के खिलाफ मेरे सिर को टक्कर देने के आधे दिन के बाद, मैंने पाया कि जिन धाराओं में समस्याएं आ रही हैं उनमें अंतराल में अतिरिक्त बाइट्स (जो कि जीजीआईपी डेटा का हिस्सा नहीं हैं) शामिल हैं।मैं Gzip फ़ाइलों के साथ कैसे काम कर सकता हूं जिसमें अतिरिक्त डेटा है?
यह मुझे अजीब लगा कि अजगर दो कारणों से इन फाइलों के साथ काम नहीं कर सकते हैं के रूप में हमलों:
- दोनों Gzip और 7zip मुद्दे के बिना इन "गद्देदार" फ़ाइलें खोलने के लिए सक्षम हैं। (। Gzip संदेश
decompression OK, trailing garbage ignored
, 7zip चुपचाप सफल होता है पैदा करता है) दोनों Gzip और अजगर डॉक्स संकेत मिलता है कि यह काम करना चाहिए लगता है: (जोर मेरा)
यह संभव होना चाहिए संपीड़ित डेटा के वास्तविक आकार के बावजूद किसी भी संपीड़न विधि, के साथ संपीड़ित डेटा के अंत का पता लगाएं। विशेष रूप से, decompressor एक रिकार्ड उन्मुख फाइल सिस्टम पर एक वैध संपीड़ित फ़ाइल को संलग्न अतिरिक्त डेटा का पता लगाने और छोड़ने के लिए, या में सक्षम होना चाहिए जब संकुचित डेटा केवल एक के गुणकों में एक डिवाइस से पढ़ा जा सकता है कुछ ब्लॉक आकार।
एक
GzipFile
वस्तु कीclose()
विधि कॉलिंग fileobj, बंद नहीं होती है जब से तुम संकुचित डेटा के बाद और अधिक सामग्री संलग्न करने के लिए इच्छा हो सकती है। यह आपको ऑब्जेक्ट को fileobj के रूप में लिखने के लिए खोला गया है, औरStringIO
ऑब्जेक्ट कीgetvalue()
विधि का उपयोग करके परिणामी मेमोरी बफर पुनर्प्राप्त करने की अनुमति देता है।Python's
zlib.Decompress.unused_data
:एक स्ट्रिंग जो संकुचित डेटा के अंत अतीत किसी भी बाइट का है। यही है, यह संपीड़न डेटा युक्त अंतिम बाइट तक
""
बनी हुई है। यदि संपूर्ण स्ट्रिंग संपीड़ित डेटा को शामिल करने के लिए निकली है, तो यह खाली स्ट्रिंग""
है।यह निर्धारित करने का एकमात्र तरीका है कि संकुचित डेटा समाप्त होने की स्ट्रिंग वास्तव में इसे डिकंप्रेस कर रही है। इसका अर्थ यह है कि जब संपीड़ित डेटा में एक बड़ी फ़ाइल का हिस्सा होता है, तो आप केवल डेटा को पढ़ने और इसे कुछ गैर-खाली स्ट्रिंग द्वारा किसी डिकंप्रेशन ऑब्जेक्ट के
decompress()
विधि में तब तक प्राप्त कर सकते हैं जब तकunused_data
विशेषता अब नहीं है खाली स्ट्रिंग।
यहाँ चार दृष्टिकोण मैं कोशिश की है कर रहे हैं।
# approach 1 - gzip.open
with gzip.open(filename) as datafile:
data = datafile.read()
# approach 2 - gzip.GzipFile
with open(filename, "rb") as gzipfile:
with gzip.GzipFile(fileobj=gzipfile) as datafile:
data = datafile.read()
# approach 3 - zlib.decompress
with open(filename, "rb") as gzipfile:
data = zlib.decompress(gzipfile.read()[10:])
# approach 4 - zlib.decompressobj
with open(filename, "rb") as gzipfile:
decompressor = zlib.decompressobj()
data = decompressor.decompress(gzipfile.read()[10:])
मैं कुछ गलत कर रहा हूँ (इन उदाहरणों अजगर 3.1 हैं, लेकिन मैं 2.5 2.7 परीक्षण किया है और और एक ही समस्या थी।)?
अद्यतन
ठीक है, जबकि gzip
के साथ समस्या यह मॉड्यूल में एक बग हो रहा है, मेरे zlib
समस्याओं स्व-प्रेरित कर रहे हैं। ;-)
gzip.py
में खोदने के दौरान मुझे एहसास हुआ कि मैं क्या गलत कर रहा था - डिफ़ॉल्ट रूप से, zlib.decompress
et al। zlib-wrapped धाराओं की अपेक्षा करें, नंगे डिफ्लेट स्ट्रीम न करें। wbits
के लिए ऋणात्मक मान में गुजरकर, आप zlib शीर्षलेख को छोड़ने और कच्ची धारा को डीक्रोप्रेस करने के लिए zlib
बता सकते हैं। इन दोनों कार्य:
# approach 5 - zlib.decompress with negative wbits
with open(filename, "rb") as gzipfile:
data = zlib.decompress(gzipfile.read()[10:], -zlib.MAX_WBITS)
# approach 6 - zlib.decompressobj with negative wbits
with open(filename, "rb") as gzipfile:
decompressor = zlib.decompressobj(-zlib.MAX_WBITS)
data = decompressor.decompress(gzipfile.read()[10:])
मैं वास्तव में समस्या को दूर करने, जबकि 'gzip' के internals के साथ एक सा बारे में mucked चाहते हैं, लेकिन इसे ठीक करने के मेरे लिए नहीं हुआ था वहां समस्या और मेरी स्क्रिप्ट के साथ संशोधित मॉड्यूल पैकेज।यह नरक के रूप में बदसूरत है, लेकिन ऐसा लगता है कि यह अभी भी सबसे अच्छा उपलब्ध विकल्प हो सकता है। : -/ –
@ बेन: यह स्वयं निहित है कि कम से कम एक बड़ी लागत नहीं है; सिर्फ एक फाइल यह देशी मॉड्यूल के साथ और अधिक परेशान है। –
एक काम के रूप में, यह मानते हुए कि यह आपके कोड पर आकार या समय की बाधाओं को तोड़ नहीं देता है, आप त्रुटि प्राप्त करने के बाद एक बाइट में पढ़ सकते हैं। एक सूची में प्रत्येक बाइट संलग्न करें, जब आप 'gzipped फ़ाइल नहीं' पैरामीटर के साथ एक और IOError प्राप्त करते हैं, तो आप डेटा के अंत तक पहुंच गए हैं, '' इसमें शामिल हों और –