perl - 如何检测latin1和UTF-8?

标签 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,能够得到是/否也同样有用。

最佳答案

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

因此,解决方案是尝试使用 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);
    


  • 笔记
  • 假设文本是有效的 UTF-8 或有效的 iso-8859-1,如果以下所有内容都为真,我的解决方案只会猜测错误:
  • 文本使用 iso-8859-1(与 UTF-8 相反)编码,
  • [<80><81><82><83><84><85><86><87><88><89><8A><8B><8C><8D><8E>中的至少一项<8F><90><91><92><93><94><95><96><97><98><99><9A><9B><9C><9D><9E><9F >¡£€¥|§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÔÔÕÖ×ØÙÚÛÜÝÞÐÐÑÒÒÔÕÖ×ØÙÚÛÜÝÞÐÐÍÍÍÍÍÍÍÐÍÍÍÍÍÚ101
  • [ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß]的所有实例后跟其中之一 [<80><81><82><83><84><85><86><87><88><87><88> <8C><8D><8E><8F><90><91><92><93><94><95><96><97><98><99><9A><9B><9C ><9D><9E><9F>¡£¤¥|§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿],
  • [àáâãäåæçèéêëìíîï] 的所有实例后跟两个 [<80><81><82><83><84><85><86><87><88><89><8A><8B><8C ><8D><8E><8F><90><91><92><93><94><95><96><97><98><99><9A><9B><9C>< 9D><9E><9F>¡£££¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿],
  • [ðñòóôõö÷] 的所有实例后跟三个 [<80><81><82><83><84><85><86><87><88><89><8A><8B>< 8C><8D><8E><8F><90><91><92><93><94><95><96><97><98><99><9A><9B><9C> <9D><9E><9F>¡£¤¥|§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿],
  • [øùúûüýþÿ] 都不存在,并且
  • [<80><81><82><83><84><85><86><87><88><89><8A><8B><8C><8D><8E><8F 都没有><90><91><92><93><94><95><96><97><98><99><9A><9B><9C><9D><9E><9F>< NBSP>¡¢£¤¥|§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿] 存在,除非前面提到过。



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

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

    关于perl - 如何检测latin1和UTF-8?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22868271/

    相关文章:

    perl - 读取 Perl 中的可选命令行参数

    perl - 在 perl 中使用正则表达式匹配创建哈希

    xml - perl LibXML 编写XML文档

    unicode - 标准化 unicode

    python - 使用 xlrd 打开 Excel 文件时出现编码错误

    perl - 在数码照片中,如何检测一座山是否被云层遮挡?

    python - 将字符串 '\u05d9\u05d7\u05e4\u05d9\u05dd' 转换为其在 python 中的 unicode 字符

    android - How to encode jpeg images to H264 very fast(将图像转换为视频)

    SQL Server,如何将默认排序规则设置为unicode?

    perl - Unicode::Normalize - 查询 'Normalization From'