7

如果我打开一个文件(并直接指定一个编码):

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
4

3 回答 3

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) 
    }
于 2010-05-22T15:30:24.337 回答
5

您需要指定 UTF-16BE 或 UTF-16LE。请参阅http://perldoc.perl.org/Encode/Unicode.html#Size%2c-Endianness%2c-and-BOM

于 2010-05-22T12:19:21.017 回答
1

你试图做的事情是不可能的。

您正在阅读文本而不指定编码,因此每个包含换行符(默认\x0a)的字节都以一行结尾。但是这个换行符很可能位于 UTF-16 字符的中间,在这种情况下,您的下一行无法被解码。如果您的数据是 UTF-16LE,这将一直发生 - 换行符是\x0a \x00. 如果你有 UTF16-BE,你可能会很幸运(换行符是\x00 \x0a),直到你得到一个\x0a高字节的字符。

所以,不要那样做,以正确的编码打开文件。

于 2010-05-22T14:10:04.830 回答