【问题标题】:How can I decode UTF-16 data in Perl when I don't know the byte order?当我不知道字节顺序时,如何在 Perl 中解码 UTF-16 数据?
【发布时间】:2011-02-22 16:35:35
【问题描述】:

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

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

【问题讨论】:

  • 您能给我们看一下该文件前几个字节的转储吗?

标签: perl decode utf-16


【解决方案1】:

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 如果你不总是有一个文件,你只得到一个字符串怎么办?
    • 这并非不可能:请参阅我的回答,了解如何处理不完整的字节序列。
    【解决方案3】:

    如果您简单地指定“UTF-16”,Perl 将寻找字节顺序标记 (BOM) 来确定如何解析它。如果没有 BOM,它就会爆炸。在这种情况下,您必须通过为 little-endian 指定“UTF-16LE”或为 big-endian 指定“UTF-16BE”来告诉 Encode 您具有哪种字节顺序。

    虽然您的情况还有其他问题,但如果不查看文件中的数据就很难判断。两个 sn-ps 都出现相同的错误。如果我没有 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) 
        }
    

    【讨论】:

    • 你知道,如果我将字符串连接到一个大缓冲区中,我可以成功地对其使用解码。
    • 您可以一次解码整个内容,因为它会看到整个字符串的 BOM。将其分解为单独的行意味着 BOM 仅适用于第一个块。 Encode 并没有做任何特别的事情来尝试猜测一个字符串与另一个字符串有某种关联。
    猜你喜欢
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    • 2019-12-24
    • 2019-07-12
    • 1970-01-01
    • 2019-08-16
    相关资源
    最近更新 更多