在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上死掉)吗?
答案 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);