perl Encode :: Guess有无提示-检测utf8

时间:2018-11-04 23:55:02

标签: perl utf-8 encode utf

我对Encode :: Guess感到困惑。假设这是我的perl代码:

use strict; 
use warnings;
use 5.18.2;
use Encode;
use Encode::Guess qw/utf8 iso-8859-1/;
use open IO => ':encoding(UTF-8)', ':std';
my $str1 = "1 = educa\x{c3}\x{a7}\x{c3}\x{a3}o";
my $str2 =  "2 = educa\x{e7}\x{e3}o";

say "A: ".&fixEnc($str1);
say "B: ".&fixEnc($str1,'hint');
say "C: ".&fixEnc($str2);
say "D: ".&fixEnc($str2,'hint');
say "";

sub fixEnc() {
    my $data = $_[0];
    my $enc = "";
    if ($_[1]) {
        $enc = guess_encoding($data,qw/utf8 iso-8859-1/);
    } else {
        $enc = guess_encoding($data);
    };
    if (!ref($enc)) {
        return "ERROR: Can't guess: $enc for $data";
    } else {
        my $utf8 = decode($enc->name, $data);
        $utf8 = "encoding guess: ".$enc->name."; result: $utf8";
        return $utf8;
    };
};

它产生:

A1: ERROR: Can't guess: iso-8859-1 or utf8 for 1 = educação
B2: ERROR: Can't guess: utf8 or iso-8859-1 for 1 = educação
C1: encoding guess: iso-8859-1; result: 2 = educação
D1: encoding guess: iso-8859-1; result: 2 = educação

现在,如果我替换为“使用Encode :: Guess qw / utf8 iso-8859-1 /;”通过'使用Encode :: Guess;'我得到

A2: encoding guess: utf8; result: 1 = educação
B2: ERROR: Can't guess: iso-8859-1 or utf8 for 1 = educação
C2: ERROR: Can't guess: No appropriate encodings found! for 2 = educação
D2: encoding guess: iso-8859-1; result: 2 = educação

是什么导致差异?特别是当我提示utf8时,为什么没有猜到utf8?

编辑:我在下面发布了答案。基本上,人们意识到Guess会采用字符编码,并且不会说葡萄牙语! “educação”(不是葡萄牙语)是上面字符串1的正确拉丁语1版本,Guess无法将其与UTF8版本educação区别开来(不同于葡萄牙语)。

2 个答案:

答案 0 :(得分:1)

我认为这是怎么回事。使用use Encode::Guess qw/utf8 iso-8859-1/;时,“提示”没有区别(抱歉,不清楚!),所以我们只有

A1/B1: ERROR: Can't guess: iso-8859-1 or utf8 for 1 = educação

和     C1 / D1:编码猜测:iso-8859-1;结果:2 =educação

对于A1 / B2,字符串可以是UTF8(educação),也可以是latin1(educaçÃo)。第二个看起来不正确,但是Encode :: Guess无法分辨-Guess进行字符编码并且不会讲葡萄牙语!

现在,如果我替换为“使用Encode :: Guess qw / utf8 iso-8859-1 /;”通过“使用Encode :: Guess;”我得到

A2: encoding guess: utf8; result: 1 = educação

latin-1不再是一个选项(它不是默认选项的一部分),因此结果显示为utf8。

B2: ERROR: Can't guess: iso-8859-1 or utf8 for 1 = educação

在B2中,点击成功后,我们又回到了上述情况,而Guess无法决定。

对于C2:

C2: ERROR: Can't guess: No appropriate encodings found! for 2 = educação

这很有意义,因为latin-1不是默认值的一部分。终于在D2中

D2: encoding guess: iso-8859-1; result: 2 = educação
提示

latin-1,因此可以检测到编码。

答案 1 :(得分:0)

很难肯定地说,因为有一些问题使编码检测变得困难。

首先是iso-8859-1与utf8共享几乎所有代码点的事实。除非字符串开头没有确定的字节顺序标记或iso-8859-1中不存在的字符,否则Encode :: Guess确实只是在猜测。

第二个在perldocs的Encode::Guess caveats中提到。 Encode :: Guess使用“试错”算法遍历文本,以消除所有提供的编码中的一种。自然,编码越相似,模块的准确性就越低。

第三,当您在use语句中未指定允许的编码类型时,模块将对其进行比较。这与反复试验方法以及utf8与iso-8859-1代码点的重叠相结合,意味着Encode :: Guess可以根据传递给该方法的参数得出不同的结论。我想如果您对另外两种不同的编码(例如utf8和7bit-jis)进行检查,将会得到更加一致的结果。

最后,Perl具有more than one implementation of utf8,因此当您没有明确指定'utf8'编码时,也有可能使用了可能会改变结果的其他实现。我对Perl的内部知识了解不足,无法确定在这种情况下是怎么回事。