如何检测latin1和UTF-8?

时间:2014-04-04 16:33:53

标签: perl unicode encoding utf-8 latin1

我从XML文件中提取字符串,即使它应该是纯UTF-8,但事实并非如此。我的想法是

#!/usr/bin/perl
use warnings;
use strict;
use Encode qw(decode encode);
use Data::Dumper;

my $x = "m\x{e6}gtig";
my $y = "m\x{c3}\x{a6}gtig";

my $a = encode('UTF-8', $x);
my $b = encode('UTF-8', $y);

print Dumper $x;
print Dumper $y;
print Dumper $a;
print Dumper $b;

if ($x eq $y) { print "1\n"; }
if ($x eq $a) { print "2\n"; }
if ($a eq $y) { print "3\n"; }
if ($a eq $b) { print "4\n"; }
if ($x eq $b) { print "5\n"; }
if ($y eq $b) { print "6\n"; }

输出

$VAR1 = 'm�gtig';
$VAR1 = 'mægtig';
$VAR1 = 'mægtig';
$VAR1 = 'mægtig';
3

认为只有latin1字符串会增加其长度,但编码已经是UTF-8也会使它更长。所以我无法通过这种方式检测到latin1与UTF-8。

问题

我想最终总是使用UTF-8字符串,但是如何检测它是latin1还是UTF-8,所以我只转换latin1字符串?

如果字符串是UTF-8,那么能够得到是/否。

1 个答案:

答案 0 :(得分:7)

由于UTF-8的某些属性,使用iso-8859-1编码的文本不太可能是有效的UTF-8,除非它使用两种编码 [1] 进行相同的解码。

因此,解决方案是尝试使用UTF-8对其进行解码。如果失败,请使用iso-8859-1对其进行解码。由于使用iso-8859-1进行解码是一种无操作,我将跳过这一步。

  • utf8 :: implementation:

    my $decoded_text = $utf8_or_latin1;
    utf8::decode($decoded_text);
    
  • Encode :: implementation:

    use Encode qw( decode_utf8 );
    
    my $decoded_text =
       eval { decode_utf8($utf8_or_latin1, Encode::FB_CROAK|Encode::LEAVE_SRC) }
          // $utf8_or_latin1;
    

现在,你说你想要UTF-8。 UTF-8是通过编码解码文本获得的。

  • utf8 :: implementation:

    my $utf8 = $decoded_text;
    utf8::encode($utf8);
    
  • Encode :: implementation:

    use Encode qw( encode_utf8 );
    
    my $utf8 = encode_utf8($decoded_text);
    

注释

  1. 假设文本是有效的UTF-8或有效的iso-8859-1,如果满足以下所有条件,我的解决方案只会猜错:

    • 使用iso-8859-1(而不是UTF-8)对文本进行编码,
    • [α>< 81>< IT>&nbsp>< IT><>< IT><><>< IT><><><>< IT><> ><>>>> 89>< 8A>< 8B>< 8C>< 8D>< 8E>< 8f中;
      < 90>< 91>< 92>&LT 93基;< 94> < 95>< 96>< 97>< 98>< 99>< 9A>< 9B>< 9C>< 9D>< 9E>< 9F>
      < NBSP>¡¢£¤¥|§¨©ª«¬< SHY>®°±²³'μ¶·¸¹º»¼½¾¿
      àÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß
      àáâãäåæçèéêëìíîïðñòóôõö÷
      ]在场,
    • [< 80>< IT>< IT>< IT><><><><><><>< 8>< 8>< 8> ; 87>< 88>< 89>< 8A>< 8B>< 8C>< 8D>< 8E>< 8f中;
      < 90>< 91>< 92&GT ;&LT 93基;< 94>< 95>< 96>< 97>< 98>< 99>< 9A>< 9B>< 9C>< 9D>< 9E>&LT ; 9F>
      < NBSP>¡¢£¤¥|§¨©ª«¬< SHY>®°±²³'μ¶·¸¹º»¼½¾¿]
    • [àáâããååæçèéêëìíï]的所有实例之后是两个[实施< 80>< IT>< IT><><><><><><><><><><><><>>>>> 87> ;< 88>< 89>< 8A>< 8B>< 8C>< 8D>< 8E>< 8f中;
      < 90>< 91>< 92>&LT 93基;< 94>< 95>< 96>< 97>< 98>< 99>< 9A>< 9B>< 9C>< 9D>< 9E>< 9F&GT ;
      < NBSP>¡¢£¤¥|§¨©ª«¬< SHY>®°±²³'μ¶·¸¹º»¼½¾¿]
    • 所有[ðñòõ÷]的实例之后是三个[
      < 80>< IT>< IT>< IT>< IT><>< IT><><><><>>> 87>< 88>< 89>< 8A>< 8B>< 8C>< 8D>< 8E>< 8f中;
      < 90>< 91>< 92> &LT 93基;< 94>< 95>< 96>< 97>< 98>< 99>< 9A>< 9B>< 9C>< 9D>< 9E>< 9F>
      < NBSP>¡¢£¤¥|§¨©ª«¬< SHY>®°±²³'μ¶·¸¹º»¼½¾¿]
    • [øùúûüýþÿ]都不存在,
    • [α>< 81>< 81>< 82>&#82>&#89><><><> < 8A>< 8B>< 8C>< 8D>< 8E>< 8f中;
      < 90>< 91>< 92>&LT 93基;< 94>< 95 GT;< 96>< 97>< 98>< 99>< 9A>< 9B>< 9C>< 9D>< 9E>< 9F>
      < NBSP>除了前面提到的地方之外,还有“¥”|“¨«¬< SHY>®¯°±³³'μ¶·¸¹º»¼½¾

    (< 80> ..< 9F>是未分配或不可打印的控制字符,不确定是哪个。)

    换句话说,该代码非常可靠。