我如何猜测Perl中字符串的编码?

时间:2009-12-28 17:52:13

标签: perl unicode string

我有一个Unicode字符串,不知道它的编码是什么。当Perl程序读取此字符串时,是否存在Perl将使用的默认编码?如果是这样,我怎么知道它是什么?

我试图从输入中删除非ASCII字符。我在一些论坛上发现了这一点:

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

如果未指定输入编码,上述工作方式如何?是否应该如下指定?

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

3 个答案:

答案 0 :(得分:30)

要找出未知使用的编码,您只需要试一试。模块Encode::DetectEncode::Guess使其自动化。 (如果您在编译Encode :: Detect时遇到问题,请尝试使用它的分叉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.

答案 1 :(得分:4)

Encode模块有一种方法可以尝试这样做。您decode原始八位字节与您认为的编码是什么。如果八位字节不代表有效的编码,它会爆炸并用eval捕获它。否则,您将返回正确编码的字符串。例如:

 use Encode;

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

这样做的缺点是相同的八位位组序列在多种编码中都是有效的

在即将到来的Effective Perl Programming, 2nd Edition中我还有更多要说的内容,其中有关于处理Unicode的整章。我认为如果我发布整件事情,我的出版商会生气。 :)

您可能还希望看到Juerd's Unicode Advice以及Perl附带的一些Unicode文档。

答案 2 :(得分:-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);