实际上我必须解析一些可以是任何形式的endian(Big或Little)的文件。如果我使用一个编码并解析其他编码,Perl解释器就会死掉。
open (my $fh, "<:raw:encoding(UTF-16LE):crlf", $ARGV[0]) or die cannot open file for reading : $! \n";
或
open (my $fh, "<:raw:encoding(UTF-16BE):crlf", $ARGV[0]) or die cannot open file for reading : $! \n";
输出(对于LE中的文件和perl的编码为BE)
UTF-16BE:Malformed HI surrogate dc00 at toASCII.pl line 123.
答案 0 :(得分:5)
大多数UTF-16le文件都是有效的UTF-16be文件,反之亦然。例如,无法判断0A 00
是否表示U + 000A(UTF-16le)或U + 0A00(UTF-16be)。所以,假设没有BOM,你必须猜测。
可能的启发式(按可靠性的降序排列):
FF FE
开头,则必须为UTF-16le。FE FF
开头,则必须为UTF-16be。0A 00
或0D 00
,那么它可能是UTF-16le。00 0A
或00 0D
,那么它可能是UTF-16be。xx 00
且很少00 xx
,那么它可能是UTF-16le。00 xx
且很少xx 00
,那么它可能是UTF-16be。注意:
您可以使用:raw
在文件中啜饮,对其执行部分或全部上述测试以确定编码,然后使用decode
和s/\r\n/\n/g
。
答案 1 :(得分:1)
您不显示任何代码,但一般情况下,除非您知道应该从文件中读取哪些值,否则无法确定文件的字节顺序。例如,许多文件格式在开头保留几个字节以指示格式是什么,如果这适用于您正在处理的数据,那么您只需read
这些字节,并且如果更改打开模式,则你没有得到你期待的东西
或者,由于如果选择了错误的格式,程序将会死亡,那么您可以使用它来测试所选格式是否正确。这样的事情应该适合
my $file = $ARGV[0];
open my $fh, '<:raw:encoding(UTF-16LE):crlf', $file or die $!;
eval { do_stuff_that_may_crash() };
if ( $@ ) {
if ( $@ =~ /Malformed HI surrogate/ ) {
open my $fh, '<:raw:encoding(UTF-16BE):crlf', $file or die $!;
do_stuff_that_may_crash();
}
else {
die $@;
}
}
但是因为听起来do_stuff_that_may_crash()
几乎就是你的所有程序,你应该找到一个更好的标准