2009-12-28 74 views
22

我有一個Unicode字符串,不知道它的編碼是什麼。當這個字符串被Perl程序讀取時,Perl會使用默認編碼嗎?如果是這樣,我怎麼知道它是什麼?我如何猜測Perl中的字符串編碼?

我想擺脫輸入中的非ASCII字符。我發現這個在一些論壇上會做到這一點

my $line = encode('ascii', normalize('KD', $myutf), sub {$_[0] = ''}); 

當沒有指定輸入編碼時,這將如何工作?是否應該像這樣指定?

my $line = encode('ascii', normalize('KD', decode($myutf, 'input-encoding'), sub {$_[0] = ''}); 
+1

糾正我,如果我錯了,但我認爲統一的整體的一點是,它沒有一個「編碼」 - 一切都在那裏。 – 2009-12-28 17:55:06

+3

您沒有Unicode字符串。你有一個充滿字節的文件,代表一些編碼中的Unicode字符串。如果您不知道文件的編碼,那麼請在文件開始處檢查字節順序標記。如果沒有物料清單,那你的運氣不好。 – 2009-12-28 17:57:07

+0

看起來你至少要問兩個單獨的問題(第1段和第2段)。 – Amnon 2009-12-28 17:57:26

回答

29

要了解哪種編碼方式未知的用途,您只需嘗試一下。模塊Encode::DetectEncode::Guess自動化。 (如果你有麻煩編譯編碼::檢測,嘗試其叉Encode::Detective代替。)

use Encode::Detect::Detector; 
my $unknown = "\x{54}\x{68}\x{69}\x{73}\x{20}\x{79}\x{65}\x{61}\x{72}\x{20}". 
       "\x{49}\x{20}\x{77}\x{65}\x{6e}\x{74}\x{20}\x{74}\x{6f}\x{20}". 
       "\x{b1}\x{b1}\x{be}\x{a9}\x{20}\x{50}\x{65}\x{72}\x{6c}\x{20}". 
       "\x{77}\x{6f}\x{72}\x{6b}\x{73}\x{68}\x{6f}\x{70}\x{2e}"; 
my $encoding_name = Encode::Detect::Detector::detect($unknown); 
print $encoding_name; # gb18030 

use Encode; 
my $string = decode($encoding_name, $unknown); 

我發現encode 'ascii'是擺脫非ASCII字符跛腳的解決方案。一切都會用問號代替;這太有用了。

# Bad example; don't do this. 
use utf8; 
use Encode; 
my $string = 'This year I went to 北京 Perl workshop.'; 
print encode('ascii', $string); # This year I went to ?? Perl workshop. 

如果你想要可讀的ASCII文本,我推薦使用Text::Unidecode。這也是一種有損編碼,但並不像上面簡單的encode那樣可怕。

use utf8; 
use Text::Unidecode; 
my $string = 'This year I went to 北京 Perl workshop.'; 
print unidecode($string); # This year I went to Bei Jing Perl workshop. 

但是,如果可以幫助,請避免使用有損編碼。如果您想稍後反轉操作,請選擇PERLQQXMLCREF中的任意一個。

use utf8; 
use Encode qw(encode PERLQQ XMLCREF); 
my $string = 'This year I went to 北京 Perl workshop.'; 
print encode('ascii', $string, PERLQQ); # This year I went to \x{5317}\x{4eac} Perl workshop. 
print encode('ascii', $string, XMLCREF); # This year I went to 北京 Perl workshop. 
+0

我收到的輸入信息總是使用拉丁字符集。我使用的標準化函數將「Café」轉換爲「Cafe」。但這並不適用於所有情況。鑑於此,你是否更喜歡使用PERLQQ或XMLCREF方法? – Maulin 2009-12-29 14:52:11

+0

不管我喜歡什麼 - 畢竟這是你的代碼和責任,只有你知道所有的情況。如果你確實對Café→Cafe感到滿意,那麼用'Text :: Unidecode'替換你的自定義函數。這在所有情況下都有效。 – daxim 2009-12-29 18:07:49

+0

謝謝。我想我會嘗試。 – Maulin 2009-12-29 18:34:59

3

Encode模塊有一種方法,您可以嘗試執行此操作。你的decode原始字節與你認爲的編碼是一樣的。如果八位字節不代表一個有效的編碼,它會爆炸,你用一個eval來捕捉它。否則,你會得到一個正確編碼的字符串。例如:

use Encode; 

my $a_with_ring = 
    eval { decode('UTF-8', "\x6b\xc5", Encode::FB_CROAK) } 
    or die "Could not decode string: [email protected]"; 

其缺點,同樣的八位位組序列可以在多種編碼

我有更多在即將到來的Effective Perl Programming, 2nd Edition,這對處理Unicode的一整章說這個是有效的。我認爲,如果我發佈整件事情,我的發佈商就會生氣。 :)

您可能還想看到Juerd's Unicode Advice以及Perl附帶的一些Unicode文檔。

-4

您可以使用下面的代碼也進行加密和解密代碼

sub ENCRYPT_DECRYPT() { 
    my $Str_Message=$_[0]; 
    my $Len_Str_Message=length($Str_Message); 

    my $Str_Encrypted_Message=""; 
    for (my $Position = 0;$Position<$Len_Str_Message;$Position++){ 
     my $Key_To_Use = (($Len_Str_Message+$Position)+1); 
      $Key_To_Use =(255+$Key_To_Use) % 255; 
     my $Byte_To_Be_Encrypted = substr($Str_Message, $Position, 1); 
     my $Ascii_Num_Byte_To_Encrypt = ord($Byte_To_Be_Encrypted); 
     my $Xored_Byte = $Ascii_Num_Byte_To_Encrypt^$Key_To_Use; 
      my $Encrypted_Byte = chr($Xored_Byte); 
     $Str_Encrypted_Message .= $Encrypted_Byte; 

    } 
    return $Str_Encrypted_Message; 
} 

my $var=&ENCRYPT_DECRYPT("hai"); 
print &ENCRYPT_DECRYPT($var); 
+0

問題是關於文本編碼,而不是關於加密。 – Flimm 2012-03-08 16:15:12

相關問題