如果我打开文件(并直接指定编码):
open(my $file,"<:encoding(UTF-16)","some.file") || die "error $!\n";
while(<$file>) {
print "$_\n";
}
close($file);
我可以很好地阅读文件内容。但是,如果我这样做:
use Encode;
open(my $file,"some.file") || die "error $!\n";
while(<$file>) {
print decode("UTF-16",$_);
}
close($file);
我收到以下错误:
UTF-16:Unrecognised BOM d at F:/Perl/lib/Encode.pm line 174
如何使其与decode
一起使用?
编辑:这是前几个字节:
FF FE 3C 00 68 00 74 00
答案 0 :(得分:12)
如果您只是指定“UTF-16”,Perl将寻找字节顺序标记(BOM)以找出如何解析它。如果没有BOM,那就会爆炸。在这种情况下,您必须通过为little-endian指定“UTF-16LE”或为big-endian指定“UTF-16BE”来告诉Encode您具有哪个字节顺序。
虽然你的情况还有其他的事情发生,但是如果没有看到文件中的数据,很难说清楚。我对两个片段都有同样的错误。如果我没有BOM并且我没有指定字节顺序,那么我的Perl就会抱怨。您使用的是哪种Perl,您拥有哪个平台?您的平台是否具有文件的本机字节顺序?根据文档,我认为我看到的行为是正确的。
此外,您不能简单地读取某些未知编码的行(无论Perl的默认编码是什么),然后将其发送到decode
。您可能最终处于多字节序列的中间。您必须使用Encode::FB_QUIET
来保存无法解码的缓冲区部分,并将其添加到下一个数据块中:
open my($lefh), '<:raw', 'text-utf16.txt';
my $string;
while( $string .= <$lefh> ) {
print decode("UTF-16LE", $string, Encode::FB_QUIET)
}
答案 1 :(得分:5)
您需要指定UTF-16BE或UTF-16LE。见http://perldoc.perl.org/Encode/Unicode.html#Size%2c-Endianness%2c-and-BOM
答案 2 :(得分:1)
你想做什么不可能。
您正在读取文本的行而未指定编码,因此包含换行符(默认\x0a
)的每个字节都会结束一行。但是这个换行符很可能在UTF-16字符的中间,在这种情况下你的下一行不能被解码。
如果您的数据是UTF-16LE,则会一直发生这种情况 - 换行符为\x0a \x00
。如果你有UTF16-BE,你可能会很幸运(换行符是\x00 \x0a
),直到你得到一个高字节\x0a
的字符。
所以,不要那样做,用正确的编码打开文件。