【问题标题】:How to detect latin1 and UTF-8?如何检测 latin1 和 UTF-8?
【发布时间】:2014-05-17 02:09:50
【问题描述】:

我正在从 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,则能够获得是/否同样有用。

【问题讨论】:

  • 您想要一个解决方案来猜测正确的字符集是什么,还是想要一些准确的?因为,后者是不可能的。
  • 如果不能准确做到,那就猜总比没有好=)
  • @deviantfan,猜测非常准确。请参阅我的答案中的脚注。
  • @ikegami:还在猜测。我并不是说这很糟糕,但这不会改变事实。
  • 您不能通过返回向您提供这些数据的人并要求他们提供有效的 UTF8 来避免这一切吗?

标签: perl unicode encoding utf-8 latin1


【解决方案1】:

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

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

  • utf8:: 实现:

    my $decoded_text = $utf8_or_latin1;
    utf8::decode($decoded_text);
    
  • 编码:: 实现:

    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:: 实现:

    my $utf8 = $decoded_text;
    utf8::encode($utf8);
    
  • 编码:: 实现:

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

注意事项

  1. 假设文本是有效的 UTF-8 或有效的 iso-8859-1,我的解决方案只有在以下所有条件都为真时才会猜错:

    • 文本使用 iso-8859-1(而不是 UTF-8)编码,
    • [
      中的至少一项

      ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿
      ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ× ØÙÚÛÜÝÞß
      àáâãäåæçèéêëììíîïðñòóôõö÷
      ] 存在,
    • [ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß] 的所有实例后跟 [
      之一

      ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸ ¹º»¼½¾¿],
    • 所有 [àáâãäåæçèéêëììîï] 实例后跟两个 [


      ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º» ¼½¾¿],
    • [ðñòóôõö÷] 的所有实例后跟三个 [


      ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º »¼½¾¿],
    • [øùúûüýþÿ] 都不存在,并且
    • 没有 [


      ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿
      ] 除了前面提到的地方。

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

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

【讨论】:

  • 如何将 utf8 编码为 utf8 不会破坏它?在我的 OP 中确实如此。
  • 在你的例子中它可以工作,我不明白为什么会这样,因为它在我的例子中失败了。
  • 我不使用 UTF-8 编码 UTF-8 字节。我不编码 UTF-8 字节,句号。我使用 UTF-8 对解码后的文本(Unicode 代码点)进行编码。
猜你喜欢
  • 2020-09-15
  • 2012-03-07
  • 1970-01-01
  • 2011-05-11
  • 2012-11-17
  • 2013-09-18
  • 1970-01-01
  • 2018-09-24
  • 1970-01-01
相关资源
最近更新 更多