2010-04-09 8 views
10

मुझे एक पायथन प्रोग्राम मिला है जो फ़ाइल को डेटा स्टोर और लिखता है। डेटा कच्चे बाइनरी डेटा है, आंतरिक रूप से str के रूप में संग्रहीत किया जाता है। मैं इसे एक यूटीएफ -8 कोडेक के माध्यम से लिख रहा हूं। हालांकि, मुझे cp1252.py फ़ाइल में UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 25: character maps to <undefined> मिलती है।मैं पाइथन में कच्चे बाइनरी डेटा कैसे लिखूं?

यह मुझे लगता है जैसे पायथन डिफ़ॉल्ट कोड पृष्ठ का उपयोग कर डेटा की व्याख्या करने की कोशिश कर रहा है। लेकिन यह एक डिफ़ॉल्ट कोड पेज नहीं है। यही कारण है कि मैं str का उपयोग कर रहा हूं, unicode नहीं।

मैं अपने सवाल लगता है कि कर रहे हैं:

  • मैं कैसे, स्मृति में कच्चे बाइनरी डेटा का प्रतिनिधित्व करते हैं अजगर में?
  • जब मैं कोडेक के माध्यम से कच्चे बाइनरी डेटा लिख ​​रहा हूं, तो मैं इसे एन्कोड/एन्कोड कैसे करूं?
+1

आप कहते हैं कि आपके पास कच्चे डेटा हैं, आप उस डेटा को पहली जगह कैसे बना रहे हैं? मुझे लगता है कि आपके पास कहीं यूनिकोड स्रोत है, लेकिन यह मुझे स्पष्ट नहीं है कि आप स्ट्रिंग में "कच्चे" यूनिकोड लिख रहे हैं, या यदि आप इसे फ़ाइल (जैसे ऑब्जेक्ट) से पढ़ रहे हैं या ... (एक उदाहरण स्ट्रिंग पोस्ट करना जो इस त्रुटि को प्रदर्शित करता है सहायक होगा!) –

उत्तर

21

नोट: इस अजगर 2. x लिए लिखा गया था सुनिश्चित नहीं है कि 3.x पर लागू हो।

स्मृति में कच्चे बाइनरी डेटा के लिए str का उपयोग सही है।
[यदि आप पाइथन 2.6+ का उपयोग कर रहे हैं, तो bytes का उपयोग करना बेहतर है, जो कि 2.6+ में str पर केवल उपनाम है, लेकिन आपकी मंशा को बेहतर तरीके से व्यक्त करता है, और अगर आप एक दिन कोड को पायथन 3 पर पोर्ट करते हैं तो मदद मिलेगी।]

जैसा कि अन्य नोट करते हैं, कोडेक के माध्यम से बाइनरी डेटा लिखना अजीब है। एक कोड कोडेक फ़ाइल में यूनिकोड और बाइट आउटपुट लेता है। आप इसे पीछे की ओर करने की कोशिश कर रहे हैं, इसलिए आपके इरादों के बारे में हमारा भ्रम ...

[और त्रुटि का आपका निदान सही दिखता है: चूंकि कोडेक यूनिकोड की अपेक्षा करता है, इसलिए पाइथन आपके स्ट्रिंग को सिस्टम के डिफ़ॉल्ट एन्कोडिंग के साथ यूनिकोड में डीकोड कर रहा है , जो चोक करता है।]

आउटपुट फ़ाइल में आप क्या देखना चाहते हैं?

  • के रूप में है फ़ाइल बाइनरी डेटा को शामिल करना चाहिए, तो:

    तो फिर तुम एक कोडेक के माध्यम से इसे भेजने नहीं करना चाहिए; आपको फ़ाइल को सीधे लिखना होगा।एक कोडेक एन्कोड सब कुछ और केवल यूनिकोड के वैध एन्कोडिंग उत्सर्जित कर सकता है (आपके मामले में, वैध यूटीएफ -8)। कोई इनपुट नहीं है जिसे आप इसे मनमाने ढंग से बाइट अनुक्रमों को छोड़ने के लिए दे सकते हैं!

    • आप UTF-8 और कच्चे बाइनरी डेटा के एक मिश्रण की आवश्यकता होती है, तो आप फ़ाइल सीधे खोलने चाहिए, और इंटरमिक्स some_datasome_text.encode('utf8') साथ का लिखते हैं ...

    नोट तथापि कि कच्चे मनमानी डेटा के साथ यूटीएफ -8 मिश्रण बहुत खराब डिज़ाइन है, क्योंकि को सौदा करने के लिए ऐसी फ़ाइलें बहुत असुविधाजनक हैं! यूनिकोड को समझने वाले टूल्स बाइनरी डेटा पर चकित होंगे, जिससे आपको देखने के लिए सुविधाजनक तरीका नहीं मिल जाएगा (फ़ाइल को संशोधित करें) फ़ाइल को छोड़ दें।

  • आप यूनिकोड में मनमाने ढंग से बाइट्स की एक दोस्ताना प्रतिनिधित्व करना चाहते हैं:

    पास data.encode('base64') कोडेक के। Base64 केवल स्वच्छ ascii (अक्षर, संख्या, और एक छोटे से विराम चिह्न) पैदा करता है तो यह स्पष्ट रूप से कुछ भी में एम्बेड किया जा सकता है, यह स्पष्ट रूप से बाइनरी डेटा के रूप में लोगों को लग रहा है, और यह काफी कॉम्पैक्ट है (थोड़ा 33% भूमि के ऊपर से अधिक)।

    पीएस आप ध्यान दें कि data.encode('base64') अजीब है।

    • .encode() यूनिकोड लेने के लिए माना जाता है लेकिन मैं इसे एक स्ट्रिंग दे रहा हूँ ?! पायथन में कई छद्म-कोडेक्स हैं जो str-> str जैसे 'बेस 64' और 'zlib' को परिवर्तित करते हैं।

    • .encode() हमेशा एक स्ट्रेट देता है लेकिन आप इसे कोडेक यूनिकोड की अपेक्षा करते हैं ?! इस मामले में इसमें केवल एसीआईआईआई होगी, इसलिए इससे कोई फर्क नहीं पड़ता। आप स्पष्ट रूप से data.encode('base64').encode('utf8') लिख सकते हैं यदि यह आपको बेहतर महसूस करता है।

  • आप एक 1 की जरूरत है: यूनिकोड को मनमाने ढंग से बाइट्स से 1 मानचित्रण: कोडेक के

    पास data.decode('latin1')latin1 मानचित्र बाइट 0-255 यूनिकोड वर्णों 0-255 के लिए बाइट्स, जो कि थोड़े सुरुचिपूर्ण हैं।

    कोडेक, ज़ाहिर है, अपने वर्ण सांकेतिक शब्दों में बदलना होगा - 128-255 UTF-8 में 2 या 3 बाइट्स के रूप में एन्कोड हैं (आश्चर्यजनक, औसत भूमि के ऊपर 50%, बेस 64 से अधिक है!)। यह 1: 1 मैपिंग होने के "लालित्य" को काफी मारता है।

    भी ध्यान रखें कि यूनिकोड वर्ण 0-255 बुरा अदृश्य/नियंत्रण वर्ण (newline, formfeed, मुलायम हाइफन, आदि) अपने बाइनरी डेटा पाठ संपादक में देखने के लिए कष्टप्रद बनाने में शामिल हैं।

    इन दोषों को ध्यान में रखते हुए, मैं लैटिन 1 की सिफारिश नहीं करता जब तक कि आप समझते हैं कि आप इसे क्यों चाहते हैं।
    मैं इसे अन्य "प्राकृतिक" एन्कोडिंग के रूप में उल्लेख कर रहा हूं जो को दिमाग में स्प्रिंग्स करता है।

0

आपको आमतौर पर str के साथ कोडेक्स का उपयोग नहीं करना चाहिए, उन्हें unicode एस में बदलने के अलावा। यदि आपको लगता है कि आप अपने यूनिकोड में "कच्चे" डेटा चाहते हैं तो शायद आपको latin-1 कोडेक का उपयोग करना चाहिए।

+0

मुझे अपने यूनिकोड में "कच्चा" डेटा नहीं चाहिए। –

+0

फिर आप कोडेक का उपयोग क्यों कर रहे हैं? –

+0

मैं कई यूनिकोड तारों के साथ-साथ एक टेक्स्ट फ़ाइल में कच्चे बाइनरी डेटा लिख ​​रहा हूं। जब मैं कच्चे बाइनरी डेटा (जिसे मैंने आंतरिक रूप से utf-8 प्रारूप में संग्रहीत किया है) को एक utf-8 कोडेक में लिखने का प्रयास करते हैं, तो मुझे cp1252 त्रुटि मिलती है। –

0

आपके पहले प्रश्न के लिए: पायथन में, नियमित तार (यानी, यूनिकोड तार नहीं) बाइनरी डेटा हैं। आपके दूसरे प्रश्न के लिए

# encode the unicode string as a string 
bytes = unicodeString.encode('utf-8') 
# add it to the other string 
raw_data += bytes 
# write it all to a file 
yourFile.write(raw_data) 

: आप, यूनिकोड तार और बाइनरी डेटा लिखने बाइनरी डेटा में यूनिकोड तार कर देते हैं और उन्हें एक साथ डाल करने के लिए चाहते हैं तो आप कच्चे डेटा write(); तब, जब आप इसे पढ़ते हैं, आप ऐसा इस तरह कार्य करें:

import codecs 
yourFile = codecs.open("yourFileName", "r", "utf-8") 
# and now just use yourFile.read() to read it 
+0

जैसा कि मैंने उल्लेख किया है, मेरे पास * नियमित स्ट्रिंग है। –

+0

और 'yourFile.write (regular_string) करने से आपको त्रुटि मिलती है? आपको नियमित स्ट्रिंग को आगे बढ़ाने की आवश्यकता नहीं है; जैसे मैंने कहा, यह पहले से ही कच्चे बाइट्स है। –

+0

@ क्रिस: क्या आप पाइथन 3 का उपयोग करने की तरह कुछ मूर्खतापूर्ण कर रहे हैं? – SamB