如何在Perl中清除无效的UTF-8?

| 我的Perl程序从磁盘文件中获取一些文本作为输入,将其包装为XML,然后将其输出到STDOUT。输入名义上是UTF-8,但有时会插入垃圾。我需要清理输出,以免发出无效的UTF-8八位位组,否则下游使用者(Sphinx)会崩溃。 至少我想知道数据是否无效,这样我可以避免将其继续传递;理想情况下,我可以只删除有问题的字节。但是,启用我能找到的所有宿命论并不能完全以perl 5.12(FWIW,
use v5.12; use warnings qw( FATAL utf8 );
生效)将我带到那儿。 我在处理序列ѭ1时特别麻烦。如果我创建的文件只包含这三个字节(
perl -e \'print \"\\xEF\\xBF\\xBE\"\' > bad.txt
),则尝试以
:encoding(UTF-8)
模式读取文件时出现
:encoding(UTF-8)
模式错误,但仅限于5.14.0以下。 5.12.3和更早的版本可以很好地阅读,以后再编写该序列。我不确定从哪儿来的5英镑(非法反向BOM),但至少有人抱怨与Sphinx一致。 不幸的是,ѭ612在5.12或5.14下不会引起错误。我更喜欢不需要编码的I / O层的检测方法,因为这只会给我留下一条错误消息,并且无法清除原始八位字节。 我确定还有更多序列需要解决,但仅处理这一序列将是一个开始。所以我的问题是:我可以在5.14之前的Perl中可靠地检测到此类问题数据吗?哪种替代程序通常可以将几乎UTF-8消毒为严格的UTF-8?     
已邀请:
        您应该阅读Encode文档的UTF-8 vs. utf8 vs. UTF8部分。 总而言之,Perl有两种​​不同的UTF-8编码。它的本机编码称为“ 7”,基本上允许任何代码点,而与Unicode标准关于该代码点的规定无关。 另一种编码称为
utf-8
(又称ѭ9。)。这仅允许被Unicode标准列为合法交换的代码点。
\"\\xEF\\xBF\\xBE\"
解释为UTF-8时,将解码为代码点U + FFFE。但这对于根据Unicode进行交换是不合法的,因此对此类事情严格的程序会抱怨。 代替使用using11ѭ(使用宽松的
utf8
编码),而应使用
decode
utf-8
编码。并阅读处理格式错误的数据部分,以了解处理或抱怨问题的不同方法。 更新:即使使用using9ѭ编码,某些版本的Perl似乎也不会抱怨U + FFFE。这似乎是一个错误。您可能只需要构建Sphinx抱怨的代码点列表并手动将其过滤掉(例如,使用
tr
)。     
        您有一个包含一些无效utf8的utf8字符串... 这将其替换为默认的\'bad char \'。
use Encode qw(decode encode);

my $octets    = decode(\'UTF-8\', $malformed_utf8, Encode::FB_DEFAULT);

my $good_utf8 = encode(\'UTF-8\', $octets,         Encode::FB_CROAK);
    

要回复问题请先登录注册