English 中文(简体)
如何在Perl中清除无效的UTF-8?
原标题:How do I sanitize invalid UTF-8 in Perl?

我的Perl程序从磁盘文件中获取一些文本作为输入,将其封装在一些XML中,然后将其输出到STDOUT。输入名义上是UTF-8,但有时会插入垃圾。我需要对输出进行净化,这样就不会发出无效的UTF-8八位字节,否则下游消费者(Sphinx)就会崩溃。

至少我想知道是否数据无效,这样我就可以避免传递它;理想情况下,我可以只删除有问题的字节。然而,启用我能找到的所有宿命论并不能让我使用perl5.12(FWIW,<code>使用v5.12;使用警告qw(FATAL utf8)生效)。

我特别在“xFExBFxBE”序列上遇到问题。如果我创建了一个只包含这三个字节的文件(perl-eprint“xEFxBFxBE”>;bad.txt),则尝试以:encoding(UTF-8)模式读取文件时出错,并使用utf8“xFFFE”不会映射到Unicode,而只能在5.14.0以下。5.12.3和更早的版本是非常好的阅读和以后写的序列。我不确定它是从哪里得到xFFFE(非法反向BOM)的,但至少投诉与斯芬克斯一致。

不幸的是,decode_utf8(“xEFxBFxBE”,1)不会导致5.12或5.14下的错误。我更喜欢一种不需要编码I/O层的检测方法,因为这只会给我留下一条错误消息,而且无法清除原始八位字节。

我确信还有更多的序列需要处理,但处理这一个序列将是一个开始。所以我的问题是:我能用5.14之前的perl可靠地检测这种问题数据吗?什么样的替换例程通常可以将almost-UTF-8净化为严格的UTF-8?

最佳回答

您应该阅读UTF-8与UTF8与UTF8部分http://search.cpan.org/perldoc?Encode“rel=”noreferrer“>编码文档。

总之,Perl有两种不同的UTF-8编码。它的原生编码被称为utf8,基本上允许任何代码点,无论Unicode标准对该代码点有何规定。

另一种编码称为utf-8(也称为utf-8-strict)。这只允许被Unicode标准列为合法的代码点进行交换。

“xEFxBFxBE”,当解释为UTF-8时,解码为代码点U+FFFE。但根据Unicode,这对于交换是不合法的,所以对这种事情严格的程序会抱怨。

不使用decode_utf8(使用laxutf8encoding),而是使用decodeoutf-8处理格式错误的数据部分,了解处理或投诉问题的不同方式。

更新:Perl的某些版本似乎并不抱怨U+FFFE,即使在使用utf-8-strict编码时也是如此。这似乎是一个错误。您可能只需要建立一个Sphinx抱怨的代码点列表,并手动过滤掉它们(例如,使用tr)。

问题回答

您有一个utf8字符串,其中包含一些无效的utf8。。。

这将用默认的坏字符替换它。

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);




相关问题
Why does my chdir to a filehandle not work in Perl?

When I try a "chdir" with a filehandle as argument, "chdir" returns 0 and a pwd returns still the same directory. Should that be so? I tried this, because in the documentation to chdir I found: "...

How do I use GetOptions to get the default argument?

I ve read the doc for GetOptions but I can t seem to find what I need... (maybe I am blind) What I want to do is to parse command line like this myperlscript.pl -mode [sth] [inputfile] I can use ...

Object-Oriented Perl constructor syntax and named parameters

I m a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot. package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I ...

Where can I find object-oriented Perl tutorials? [closed]

A Google search yields a number of results - but which ones are the best? The Perl site appears to contain two - perlboot and perltoot. I m reading these now, but what else is out there? Note: I ve ...