Perl:从文件中间读取时如何避免正则表达式UTF-8错误

时间:2015-11-02 10:14:50

标签: regex perl utf-8

open(FILE, '<:utf8', $file) or die; seek(FILE, $readFrom, 0); read(FILE, $_, $size);中搜索后读取一个utf8编码的文件,有时&#34;分解&#34;一个unicode char,因此读取字符串的开头是无效的UTF-8。

如果你那么做,例如s{^([^\n]*\r?\n)}{}i剥离不完整的第一行,你得到&#34;格式错误的UTF-8字符(致命)&#34;错误。

如何解决这个问题?

How do I sanitize invalid UTF-8 in Perl?中列出的一个解决方案是删除所有无效的UTF-8字符:

tr[\x{9}\x{A}\x{D}\x{20}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}][]cd;

然而,搜索整个字符串似乎有些过分,因为它只是读取字符串中可以被破坏的第一个字节。

任何人都可以建议一种方法来只删除一个初始的无效字符(或者使上述替换不会在格式错误的UTF-8上死掉)吗?

1 个答案:

答案 0 :(得分:4)

以字节形式读取流,在开始时删除部分字符,确定最后一个完整字符的结束位置,然后解码剩下的字符。

use Encode qw( STOP_AT_PARTIAL );
use Fcntl  qw( SEEK_TO );

my $encoding = Encode::find_encoding('UTF-8');

open(my $FILE, '<:raw', $file) or die $!;
seek($FILE, $readFrom, SEEK_TO) or die $!;
my $bytes_read = read($FILE, my $buf, $size);
defined($bytes_read) or die $!;

$buf =~ s/^[\x80-\xBF]+//;

my $str = $encoding->decode($buf, STOP_AT_PARTIAL);

如果您想了解更多内容,请使用read的4-arg表格,此时不要跳过任何内容。

my $bytes_read = read($FILE, $buf, $size, length($buf));
defined($bytes_read) or die $!;

$str .= $encoding->decode($buf, STOP_AT_PARTIAL);

相关阅读:Convert UTF-8 byte stream to Unicode