2009-12-28 33 views
22

Tôi có một chuỗi Unicode và không biết mã hóa của nó là gì. Khi chuỗi này được đọc bởi một chương trình Perl, có mã hóa mặc định mà Perl sẽ sử dụng không? Nếu có, làm thế nào tôi có thể tìm ra nó là gì?Làm thế nào tôi có thể đoán mã hóa của một chuỗi trong Perl?

Tôi đang cố loại bỏ các ký tự không phải ASCII khỏi đầu vào. Tôi tìm thấy điều này trên một số diễn đàn sẽ làm điều đó

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

Điều này sẽ hoạt động như thế nào khi không có mã hóa đầu vào được chỉ định? Nó có nên được chỉ định như vậy không?

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

Đúng tôi nếu tôi là sai, nhưng tôi nghĩ rằng toàn bộ các điểm Unicode là nó không có "mã hóa" - mọi thứ đều ở đó. –

+3

Bạn không có chuỗi Unicode. Bạn có một tập tin đầy đủ các byte đại diện cho một chuỗi Unicode trong một số mã hóa. Nếu bạn không biết mã hóa của tệp, hãy kiểm tra điểm đánh dấu thứ tự byte ở đầu tệp. Nếu không có BOM, bạn sẽ không may mắn. –

+0

Có vẻ như bạn đang hỏi ít nhất hai câu hỏi riêng biệt (đoạn 1 và 2). – Amnon

Trả lời

29

Để tìm hiểu mã hóa một số thứ chưa biết, bạn chỉ cần thử và xem. Các mô-đun Encode::DetectEncode::Guess tự động hóa điều đó. (Nếu bạn gặp khó khăn khi biên soạn Mã hóa :: Phát hiện, hãy thử ngã ba của nó Encode::Detective để thay thế.)

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); 

tôi thấy encode 'ascii' là một giải pháp què cho việc loại bỏ các ký tự ASCII. Mọi thứ sẽ được thay thế bằng các dấu hỏi; điều này là quá mất mát để có ích.

# 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. 

Nếu bạn muốn văn bản ASCII có thể đọc được, tôi khuyên bạn nên Text::Unidecode thay thế. Đây cũng là một mã hóa mất dữ liệu, nhưng không phải là khủng khiếp như đồng bằng encode ở trên.

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. 

Tuy nhiên, tránh những mã hóa mất dữ liệu này nếu bạn có thể trợ giúp. Trong trường hợp bạn muốn đảo ngược hoạt động sau, hãy chọn một trong số PERLQQ hoặc XMLCREF.

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

Dữ liệu nhập tôi nhận luôn sử dụng bộ ký tự Latinh. Chức năng chuẩn hóa mà tôi sử dụng sau đó sẽ chuyển đổi "Café" thành "Cafe". Điều này không hoạt động trong mọi trường hợp. Cho điều này, bạn vẫn thích sử dụng phương pháp PERLQQ hoặc XMLCREF? – Maulin

+0

Nó không quan trọng những gì tôi thích - đó là mã của bạn và trách nhiệm sau khi tất cả, và chỉ có bạn biết tất cả các trường hợp. Nếu bạn thực sự hài lòng với Café → Cafe, hãy thay thế chức năng tùy chỉnh của bạn bằng 'Text :: Unidecode'. Điều đó không hoạt động trong mọi trường hợp. – daxim

+0

Cảm ơn. Tôi nghĩ tôi sẽ thử điều đó. – Maulin

3

Mô-đun Encode có cách bạn có thể thử thực hiện việc này. Bạn decode octet thô với những gì bạn nghĩ là mã hóa. Nếu octet không đại diện cho một mã hóa hợp lệ, nó sẽ thổi lên và bạn bắt nó bằng một eval. Nếu không, bạn lấy lại một chuỗi được mã hóa đúng cách. Ví dụ:

use Encode; 

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

này có nhược điểm mà các chuỗi octet tương tự có thể có giá trị trong nhiều mã hóa

Tôi có nhiều điều để nói về điều này trong sắp tới Effective Perl Programming, 2nd Edition, trong đó có cả một chương về đối phó với Unicode . Tôi nghĩ rằng nhà xuất bản của tôi sẽ phát điên nếu tôi đăng tải toàn bộ nội dung. :)

Bạn cũng có thể muốn xem Juerd's Unicode Advice, cũng như một số tài liệu Unicode đi kèm với Perl.

-4

Bạn có thể sử dụng đoạn mã sau cũng có, để mã hóa và giải mã các mã

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

Câu hỏi đặt ra là về mã hóa văn bản chứ không phải về mã hóa. – Flimm

Các vấn đề liên quan