在查找后读取 utf8 编码的文件,如 open(FILE, '<:utf8', $file) or die; seek(FILE, $readFrom, 0); read(FILE, $_, $size);
所示有时会“分解”unicode 字符,因此读取的字符串的开头不是有效的 UTF-8。
如果你然后这样做s{^([^\n]*\r?\n)}{}i
要删除不完整的第一行,您会收到“格式错误的 UTF-8 字符(致命)”错误。
如何解决这个问题?
一个解决方案,列于 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 上消失)吗?
最佳答案
以字节形式读取流,去掉开头的部分字符,确定最后一个完整字符的结束位置,然后解码剩下的内容。
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);
关于regex - Perl:从文件中间读取时如何避免正则表达式 UTF-8 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33475249/