2011-06-04 12 views
20

मेरा पर्ल प्रोग्राम डिस्क फ़ाइल से कुछ पाठ इनपुट के रूप में लेता है, इसे कुछ एक्सएमएल में लपेटता है, फिर इसे STDOUT तक आउटपुट करता है। इनपुट नाममात्र यूटीएफ -8 है, लेकिन कभी-कभी जंक डाला जाता है। मुझे आउटपुट को स्वच्छ करने की आवश्यकता है कि कोई अमान्य यूटीएफ -8 ऑक्टेट उत्सर्जित नहीं होता है, अन्यथा डाउनस्ट्रीम उपभोक्ता (स्फिंक्स) उड़ाएगा।मैं पर्ल में अवैध यूटीएफ -8 को कैसे स्वच्छ कर सकता हूं?

कम से कम यदि डेटा अमान्य है तो मैं इसे पास करने से बच सकता हूं; आदर्श रूप से मैं केवल अपमानजनक बाइट हटा सकता हूं। हालांकि, मुझे लगता है कि सभी घातक मुझे सक्षम बनाता है मुझे वहाँ 5.1l (FWIW, use v5.12; use warnings qw(FATAL utf8); प्रभाव में है) के साथ काफी नहीं मिलता है।

मुझे विशेष रूप से अनुक्रम "\xFE\xBF\xBE" के साथ समस्या हो रही है। अगर मैं केवल इन तीन बाइट्स (perl -e 'print "\xEF\xBF\xBE"' > bad.txt) वाली फ़ाइल बनाते हैं, तो :encoding(UTF-8) त्रुटियों के साथ फ़ाइल को पढ़ने की कोशिश कर रहा है utf8 "\xFFFE" does not map to Unicode, लेकिन केवल 5.14.0 के तहत। 5.12.3 और इससे पहले पूरी तरह से ठीक पढ़ रहे हैं और बाद में अनुक्रम लिख रहे हैं। मुझे यकीन है कि यह \xFFFE (अवैध रिवर्स-बीओएम) प्राप्त कर रहा है, लेकिन कम से कम शिकायत स्पिंक्स के साथ संगत है।

दुर्भाग्यवश, decode_utf8("\xEF\xBF\xBE", 1) 5.12 या 5.14 के तहत कोई त्रुटि नहीं बनता है। मैं एक पहचान विधि पसंद करूंगा जिसके लिए एन्कोडेड I/O परत की आवश्यकता नहीं है, क्योंकि यह मुझे एक त्रुटि संदेश के साथ छोड़ देगा और कच्चे ऑक्टेट को स्वच्छ करने का कोई तरीका नहीं है।

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

उत्तर

21

आपको Encode दस्तावेज़ों के UTF-8 vs. utf8 vs. UTF8 section को पढ़ना चाहिए।

संक्षेप में, पर्ल के दो अलग-अलग यूटीएफ -8 एन्कोडिंग हैं। इसके देशी एन्कोडिंग को utf8 कहा जाता है, और मूल रूप से किसी कोडपॉइंट की अनुमति देता है, भले ही यूनिकोड मानक उस कोडपॉइंट के बारे में क्या कहता है।

अन्य एन्कोडिंग को utf-8 (ए.के.ए. utf-8-strict) कहा जाता है। यह केवल उन कोडपॉइंट्स को अनुमति देता है जो यूनिकोड मानक द्वारा इंटरचेंज के लिए कानूनी के रूप में सूचीबद्ध हैं।

"\xEF\xBF\xBE", जब यूटीएफ -8 के रूप में व्याख्या किया गया, तो कोडपॉइंट U+FFFE पर डीकोड किया गया। लेकिन यूनिकोड के अनुसार यह विनिमय के लिए कानूनी नहीं है, इसलिए ऐसे कार्यक्रमों के बारे में सख्त कार्यक्रम शिकायत करते हैं।

इसके बजाय decode_utf8 का उपयोग कर (जो ढीला utf8 एन्कोडिंग का उपयोग करता) की

, utf-8 एन्कोडिंग के साथ decode का उपयोग करें। और समस्याओं के बारे में शिकायत करने या शिकायत करने के विभिन्न तरीकों को देखने के लिए Handling Malformed Data अनुभाग पढ़ें।

अपडेट: ऐसा लगता है कि पर्ल के कुछ संस्करण utf-8-strict एन्कोडिंग का उपयोग करते समय भी यू + एफएफएफई के बारे में शिकायत नहीं करते हैं। यह एक बग प्रतीत होता है। आपको केवल कोडपॉइंट्स की एक सूची बनाना पड़ सकता है जो स्फिंक्स शिकायत करता है और उन्हें मैन्युअल रूप से फ़िल्टर करता है (उदा। tr के साथ)।

+3

कोड उदाहरण: http: // stackoverflow।कॉम/प्रश्न/3735721/चेकलिस्ट-टू-द-यूनिकोड-वे-साथ-पर्ल/3736787 # 3736787 – daxim

+1

धन्यवाद, यह बहुत उपयोगी है। चूंकि XML में स्वीकार्य यूनिकोड वर्ण अच्छी तरह परिभाषित हैं, 'tr [\ x {9} \ x {ए} \ x {D} \ x {20} - \ x {D7FF} \ x {E000} - \ x {FFFD} \ x {10000} - \ x {10FFFF}] [] सीडी' ऐसा लगता है कि यह कम से कम 5.14 में काम करेगा। मुझे मिला एक पूरी तरह से अलग सुझाव बिल्कुल एक नए पेर्ल पर भरोसा नहीं करता है: 'iconv -c - यूटीएफ -8 से - यूटीएफ -8' तक। –

3

आप कुछ ऐसी अमान्य UTF8 युक्त एक UTF8 स्ट्रिंग ...

यह एक डिफ़ॉल्ट 'ख़राब वर्ण' के साथ यह बदल देता है।

use Encode qw(decode encode); 

my $octets = decode('UTF-8', $malformed_utf8, Encode::FB_DEFAULT); 

my $good_utf8 = encode('UTF-8', $octets,   Encode::FB_CROAK); 
संबंधित मुद्दे