2010-12-02 18 views
7

मुझे Encode::decode("utf8", $var) और utf8::decode($var) का उपयोग करने के बीच अंतर जानने के लिए कुछ दिलचस्प परिणाम मिल रहे हैं। मुझे पहले ही पता चला है कि एक चर पर पूर्व कई बार कॉल करने के परिणामस्वरूप अंततः एक त्रुटि हो सकती है "विस्तृत वर्णों के साथ स्ट्रिंग को डीकोड नहीं किया जा सकता ..." जबकि बाद की विधि खुशी से जितनी बार चाहें उतनी बार चली जाएगी, बस झूठी वापसी होगी।पर्ल: utf8 :: डीकोड बनाम एनकोड :: डीकोड

मुझे समझ में क्या समस्या आ रही है यह है कि length फ़ंक्शन डीकोड करने के लिए उपयोग की जाने वाली विधि के आधार पर अलग-अलग परिणाम देता है। समस्या उत्पन्न होती है क्योंकि मैं बाहरी फ़ाइल से "दोगुनी एन्कोडेड" utf8 टेक्स्ट से निपट रहा हूं। इस समस्या को प्रदर्शित करने के लिए, मैंने एक पंक्ति पर निम्नलिखित यूनिकोड वर्णों के साथ एक टेक्स्ट फ़ाइल "test.txt" बनाई: U + 00e8, U + 00ab, U + 0086, U + 000a। ये यूनिकोड वर्ण यूनिकोड वर्ण यू +8 एसीबी के डबल-एन्कोडिंग हैं, साथ ही साथ एक न्यूलाइन चरित्र भी। फ़ाइल को यूटीएफ 8 में डिस्क पर एन्कोड किया गया था।

#!/usr/bin/perl                                   
use strict; 
use warnings; 
require "Encode.pm"; 
require "utf8.pm"; 

open FILE, "test.txt" or die $!; 
my @lines = <FILE>; 
my $test = $lines[0]; 

print "Length: " . (length $test) . "\n"; 
print "utf8 flag: " . utf8::is_utf8($test) . "\n"; 
my @unicode = (unpack('U*', $test)); 
print "Unicode:\[email protected]\n"; 
my @hex = (unpack('H*', $test)); 
print "Hex:\[email protected]\n"; 

print "==============\n"; 

$test = Encode::decode("utf8", $test); 
print "Length: " . (length $test) . "\n"; 
print "utf8 flag: " . utf8::is_utf8($test) . "\n"; 
@unicode = (unpack('U*', $test)); 
print "Unicode:\[email protected]\n"; 
@hex = (unpack('H*', $test)); 
print "Hex:\[email protected]\n"; 

print "==============\n"; 

$test = Encode::decode("utf8", $test); 
print "Length: " . (length $test) . "\n"; 
print "utf8 flag: " . utf8::is_utf8($test) . "\n"; 
@unicode = (unpack('U*', $test)); 
print "Unicode:\[email protected]\n"; 
@hex = (unpack('H*', $test)); 

print "Hex:\[email protected]\n"; 

यह निम्न उत्पादन देता है:: मैं उसके बाद निम्न पर्ल स्क्रिप्ट चलाने

Length: 7 
utf8 flag: 
Unicode: 
195 168 194 171 194 139 10 
Hex: 
c3a8c2abc28b0a 
============== 
Length: 4 
utf8 flag: 1 
Unicode: 
232 171 139 10 
Hex: 
c3a8c2abc28b0a 
============== 
Length: 2 
utf8 flag: 1 
Unicode: 
35531 10 
Hex: 
e8ab8b0a 

यह मैं क्या उम्मीद करेंगे है। लंबाई मूल रूप से 7 है क्योंकि पर्ल सोचता है कि $ परीक्षण केवल बाइट्स की एक श्रृंखला है। एक बार डीकोड करने के बाद, पेर्ल जानता है कि $ टेस्ट वर्णों की एक श्रृंखला है जो utf8-encoded हैं (यानी 7 बाइट्स की लंबाई लौटने की बजाय, perl 4 अक्षरों की लंबाई देता है, भले ही $ परीक्षण स्मृति में 7 बाइट्स है)। दूसरे डिकोडिंग के बाद, $ टेस्ट में 2 अक्षरों के रूप में व्याख्या किए गए 4 बाइट्स होते हैं, जो मैं उम्मीद करता हूं क्योंकि एनकोड :: डिकोड ने 4 कोड पॉइंट्स ले लिए थे और उन्हें यूटीएफ 8-एन्कोडेड बाइट्स के रूप में व्याख्या किया था, जिसके परिणामस्वरूप 2 अक्षर थे। अजीब बात यह है कि जब मैं utf8 :: decode को कॉल करने के लिए कोड संशोधित करता हूं (सभी $ test = Encode :: decode ("utf8", $ test) को प्रतिस्थापित करें; utf8 :: decode ($ test) के साथ)

लगभग समान उत्पादन देता है, केवल लंबाई का परिणाम भिन्न होता है:

 
Length: 7 
utf8 flag: 
Unicode: 
195 168 194 171 194 139 10 
Hex: 
c3a8c2abc28b0a 
============== 
Length: 4 
utf8 flag: 1 
Unicode: 
232 171 139 10 
Hex: 
c3a8c2abc28b0a 
============== 
Length: 4 
utf8 flag: 1 
Unicode: 
35531 10 
Hex: 
e8ab8b0a 

यह पर्ल की तरह लगता है पहले डिकोडिंग (अपेक्षित रूप से), तो पहले डिकोडिंग के बाद पात्रों में गिना जाता है से पहले बाइट्स में गिना जाता है, लेकिन फिर बाद बाइट्स में गिना जाता है फिर से दूसरा डिकोडिंग (अपेक्षित नहीं)। यह स्विच क्यों होगा? क्या इन डिकोडिंग कार्यों के काम के बारे में मेरी समझ में कोई चूक है?

धन्यवाद,
मैट

+1

किसी भी कारण से आप उन्हें 'उपयोग' के बजाय मॉड्यूल की आवश्यकता क्यों है? –

+1

मैंने use utf8 नहीं किया क्योंकि ऐसा करने से यह पता चलता है कि आपका कोड स्वयं utf8-encoded है, जिसकी मुझे आवश्यकता नहीं है (http://perldoc.perl.org/utf8.html)। मुझे लगता है कि मैं use डी एनकोड कर सकता था, लेकिन मैं अभी नहीं हुआ। – Matt

उत्तर

3

आप utf8 pragma मॉड्यूल से कार्यों का उपयोग करने वाले नहीं हैं। Its documentation तो कहते हैं:

पर्ल से कहा कि अपनी स्क्रिप्ट को UTF-8 में लिखा है की तुलना में कुछ और के लिए इस pragma प्रयोग न करें।

Always use the Encode module, और यह प्रश्न Checklist for going the Unicode way with Perl भी देखें। unpack बहुत कम स्तर वाला है, यह आपको त्रुटि-जांच भी नहीं देता है।

आपको लगता है कि octects E8 AB 86 0A UTF-8 डबल एन्कोडिंग पात्रों और newline का परिणाम है इस धारणा के साथ गलत जा रहे हैं। यह इन वर्णों के एकल यूटीएफ -8 एन्कोडिंग का प्रतिनिधित्व है। शायद आपकी तरफ से पूरी भ्रम उस गलती से उत्पन्न होता है।

length अनुपयुक्त रूप से अधिभारित है, कुछ समय पर यह वर्णों की लंबाई, या ऑक्टेट्स में लंबाई निर्धारित करता है। Devel::Peek जैसे बेहतर टूल का उपयोग करें।

#!/usr/bin/env perl 
use strict; 
use warnings FATAL => 'all'; 
use Devel::Peek qw(Dump); 
use Encode qw(decode); 

my $test = "\x{00e8}\x{00ab}\x{0086}\x{000a}"; 
# or read the octets without implicit decoding from a file, does not matter 

Dump $test; 
# FLAGS = (PADMY,POK,pPOK) 
# PV = 0x8d8520 "\350\253\206\n"\0 

$test = decode('UTF-8', $test, Encode::FB_CROAK); 
Dump $test; 
# FLAGS = (PADMY,POK,pPOK,UTF8) 
# PV = 0xc02850 "\350\253\206\n"\0 [UTF8 "\x{8ac6}\n"] 
+2

प्रतिक्रिया के लिए धन्यवाद। पर्ल प्रलेखन का कहना है कि utf8 मॉड्यूल में कार्यों का उपयोग करना ठीक है। आपके उद्धरण के बाद वाक्य "नीचे वर्णित उपयोगिता फ़ंक्शंस उपयोगिता के बिना सीधे उपयोग योग्य हैं;", यानी किसी को "उपयोग" (perl कीवर्ड उपयोग) नहीं चाहिए, अगर किसी को इसकी आवश्यकता नहीं है, लेकिन कोई भी उपयोग कर सकता है (अंग्रेजी उपयोग) इसके कार्य। साथ ही, मुझे एहसास है कि "eaab860a" एकल-एन्कोडिंग है। मेरी फ़ाइल में octets "c3a8c2abc28b0a" है, जो डबल एन्कोडिंग हैं। यह पता चला है कि मेरा भ्रम "लंबाई" समारोह में एक बग से उत्पन्न होता है। देखें http://www.perlmonks.org/?node_id=874996 – Matt

+8

यह वास्तव में कहता है "पर्ल को यह कहने के अलावा किसी अन्य चीज़ के लिए इस प्रागमा का उपयोग न करें कि आपकी स्क्रिप्ट यूटीएफ -8 में लिखी गई है। नीचे वर्णित उपयोगिता कार्य सीधे बिना उपयोग किए जा सकते हैं utf8 का उपयोग करें; ", जिसका स्पष्ट अर्थ यह नहीं है कि" आपको utf8 pragma मॉड्यूल से फ़ंक्शंस का उपयोग नहीं करना चाहिए "। इसका मतलब है कि आपको कार्यों को आयात करने के लिए प्रज्ञा का उपयोग करने की आवश्यकता नहीं है। –

संबंधित मुद्दे