2008-10-13 12 views
9

मुझे बिल्कुल यकीन नहीं है कि इस सवाल को वास्तव में कैसे पूछना है, और मैं कोई जवाब खोजने के करीब नहीं हूं, इसलिए मुझे उम्मीद है कि कोई मेरी मदद कर सकता है।एकाधिक वर्ण एन्कोडिंग युक्त एक स्ट्रिंग के साथ काम करना

मैं एक पायथन ऐप लिख रहा हूं जो रिमोट होस्ट से जुड़ता है और बैक डेटा वापस प्राप्त करता है, जिसे मैं पायथन के अंतर्निर्मित संरचना मॉड्यूल का उपयोग करके अनपैक करता हूं। मेरी समस्या तारों के साथ है, क्योंकि उनमें कई वर्ण एन्कोडिंग शामिल हैं। यहां इस तरह के एक स्ट्रिंग का एक उदाहरण है:

"^ LThis एक उदाहरण कई^Jcharacter एन्कोडिंग के साथ gstring है ^"

कहाँ अलग एन्कोडिंग शुरू होता है और समाप्त होता है विशेष भागने वर्ण का उपयोग कर चिह्नित है:

  • ^एल - लेटिन 1
  • ^ई - मध्य यूरोप
  • ^टी - तुर्की
  • ^बी - बाल्टिक
  • ^जम्मू - जापानी
  • ^सी - सिरिलिक
  • ^जी - ग्रीक

और इसी तरह ... मैं एक तरह से यूनिकोड में स्ट्रिंग की इस तरह बदलने की आवश्यकता है, लेकिन मैं वास्तव में नहीं हूँ सुनिश्चित करें कि यह कैसे करें। मैंने पाइथन के कोडेक्स और string.encode/decode पर पढ़ा है, लेकिन मैं वास्तव में बुद्धिमान नहीं हूं। मुझे भी इसका जिक्र करना चाहिए, कि मेजबान द्वारा तारों को कैसे आउटपुट किया जाता है, इस पर मेरा कोई नियंत्रण नहीं है।

मुझे आशा है कि कोई इस पर शुरुआत करने के तरीके में मेरी सहायता कर सकता है।

+0

अपने पार्सर किसी भी त्रुटि लेकिन व्यर्थ एन्कोडिंग के साथ फेंक करता है या आप एक वैध अजगर तार के साथ छोड़ दिया जाता है,? यदि हां, तो चीजें तय की जा सकती हैं। कृपया एक उदाहरण स्ट्रिंग प्रदान करें। – DzinX

+0

मेरा मतलब ऊपर की तुलना में अन्य उदाहरण है, क्योंकि उपर्युक्त उदाहरण में केवल ASCII वर्ण हैं। – DzinX

उत्तर

4

इस तरह की स्ट्रिंग को डीकोड करने के लिए कोई अंतर्निहित कार्यक्षमता नहीं है, क्योंकि यह वास्तव में इसका अपना कस्टम कोडेक है। आपको बस उन नियंत्रण वर्णों पर स्ट्रिंग को विभाजित करने और तदनुसार इसे डीकोड करने की आवश्यकता है।

यहाँ एक (बहुत धीमी गति से) इस तरह के एक समारोह के उदाहरण है कि latin1 संभालती है और है Shift-JIS:

latin1 = "latin-1" 
japanese = "Shift-JIS" 

control_l = "\x0c" 
control_j = "\n" 

encodingMap = { 
    control_l: latin1, 
    control_j: japanese} 

def funkyDecode(s, initialCodec=latin1): 
    output = u"" 
    accum = "" 
    currentCodec = initialCodec 
    for ch in s: 
     if ch in encodingMap: 
      output += accum.decode(currentCodec) 
      currentCodec = encodingMap[ch] 
      accum = "" 
     else: 
      accum += ch 
    output += accum.decode(currentCodec) 
    return output 

एक तेजी से संस्करण str.split, या रेगुलर एक्सप्रेशन का उपयोग हो सकता है।

(इसके अलावा, आप इस उदाहरण में देख सकते हैं, "^ जम्मू" "नई पंक्ति" के लिए नियंत्रण चरित्र है, इसलिए अपने इनपुट डेटा कुछ रोचक प्रतिबंध नहीं है जा रहा है।)

3

मैं एक कोडेक लिखूंगा जो स्ट्रिंग को बढ़ाकर स्कैन कर देगा और साथ ही साथ बाइट्स को डीकोड कर देगा। अनिवार्य रूप से, आपको तारों को लगातार एन्कोडिंग के साथ अलग करना होगा और उनको डीकोड करना होगा और उन्हें उनके बाद के तारों में जोड़ना होगा।

1

मुझे लगता नहीं है आपके पास उस व्यक्ति को विश्वास करने का कोई तरीका है जो यूनिकोड पर स्विच करने के लिए अन्य मशीन होस्ट करता है?

यह यूनिकोड का आविष्कार करने के कारणों में से एक है।

+0

जैसा कि मैंने कहा है, मेरे पास होस्ट पर स्वयं का कोई नियंत्रण नहीं है। होस्ट वास्तव में एक कंप्यूटर गेम है जो मेरा ऐप कनेक्ट होता है, और मेरा मानना ​​है कि यह आंतरिक रूप से टेक्स्ट-रेंडरिंग को कैसे प्रबंधित करता है। –

2

आपको निश्चित रूप से पहले स्ट्रिंग को अलग-अलग एन्कोडिंग के साथ सबस्ट्रिंग में विभाजित करना होगा, और प्रत्येक को अलग से डीकोड करना होगा।सिर्फ मनोरंजन के लिए, अनिवार्य "एक पंक्ति" संस्करण:

import re 

encs = { 
    'L': 'latin1', 
    'G': 'iso8859-7', 
    ... 
} 

decoded = ''.join(substr[2:].decode(encs[substr[1]]) 
      for substr in re.findall('\^[%s][^^]*' % ''.join(encs.keys()), st)) 

(कोई त्रुटि जाँच, और यह भी आप कैसे '^' सबस्ट्रिंग में पात्रों को संभालने के लिए तय करने के लिए चाहता हूँ)

+0

आपने मेरे जैसा ही गलती की है! –

7

यहाँ एक अपेक्षाकृत है कैसे की सरल उदाहरण यह ...

# -*- coding: utf-8 -*- 
import re 

# Test Data 
ENCODING_RAW_DATA = (
    ('latin_1', 'L', u'Hello'),  # Latin 1 
    ('iso8859_2', 'E', u'dobrý večer'), # Central Europe 
    ('iso8859_9', 'T', u'İyi akşamlar'), # Turkish 
    ('iso8859_13', 'B', u'Į sveikatą!'), # Baltic 
    ('shift_jis', 'J', u'今日は'),  # Japanese 
    ('iso8859_5', 'C', u'Здравствуйте'), # Cyrillic 
    ('iso8859_7', 'G', u'Γειά σου'), # Greek 
) 

CODE_TO_ENCODING = dict([(chr(ord(code)-64), encoding) for encoding, code, text in ENCODING_RAW_DATA]) 
EXPECTED_RESULT = u''.join([line[2] for line in ENCODING_RAW_DATA]) 
ENCODED_DATA = ''.join([chr(ord(code)-64) + text.encode(encoding) for encoding, code, text in ENCODING_RAW_DATA]) 

FIND_RE = re.compile('[\x00-\x1A][^\x00-\x1A]*') 

def decode_single(bytes): 
    return bytes[1:].decode(CODE_TO_ENCODING[bytes[0]]) 

result = u''.join([decode_single(bytes) for bytes in FIND_RE.findall(ENCODED_DATA)]) 

assert result==EXPECTED_RESULT, u"Expected %s, but got %s" % (EXPECTED_RESULT, result) 
संबंधित मुद्दे