2016-12-15 44 views
4

其实我必须解析一些可以以任何形式的endian(Big或Little)的文件。如果我使用一种编码和解析其他Perl解释器死亡。如何在perl中检查一个文件是写成little endian还是big endian?

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

[查找系统是perl或little endian或big endian](http://stackoverflow.com/questions/2610849/finding-if-the-system-is-little-endian-or-big -endian-with-perl) –

+2

@EliSadoff这个问题询问如何查找特定的*文件*是大还是小的,而不是系统是否是。 – ThisSuitIsBlackNot

+2

为什么“my $ fh”在引号中? :-O – choroba

回答

1

你不显示任何代码,但总的来说,这是不可能告诉除非你知道你应该从文件中读取什么值,否则文件是什么字节序。例如,许多文件格式在开始时会保留几个字节以指示格式是什么,如果这适用于您正在处理的数据,那么您可以只使用read这些字节,并且如果您不需要更改打开模式得到你的期望

或者,因为如果选择了错误的格式,程序就会死掉,那么你可以用它来测试所选的格式是否正确。这样的事情应该满足

my $file = $ARGV[0]; 

open my $fh, '<:raw:encoding(UTF-16LE):crlf', $file or die $!; 

eval { do_stuff_that_may_crash() }; 

if ([email protected]) { 
    if ([email protected] =~ /Malformed HI surrogate/) { 
     open my $fh, '<:raw:encoding(UTF-16BE):crlf', $file or die $!; 
     do_stuff_that_may_crash(); 
    } 
    else { 
     die [email protected]; 
    } 
} 

,但因为它听起来像do_stuff_that_may_crash()是几乎所有的程序,你应该找到一个更好的标准

+1

不要测试'$ @','从返回eval' 1和测试返回值。 – choroba

4

大多数UTF-16LE文件是有效的UTF-16BE文件,反之亦然。例如,没有办法确定0A 00是否指示U + 000A(UTF-16le)或U + 0A00(UTF-16be)。所以,假设没有BOM,你必须猜测。

可能的试探法(以降序的可靠性顺序):

  1. U + FFFE不是字符(保证)。
    • 如果文件以FF FE开头,那么它必须是UTF-16le。
    • 如果文件以FE FF开头,那么它必须是UTF-16be。
    • 如果该文件是无效的UTF-16BE,那么它必须是UTF-16LE。
    • 如果文件不是有效的UTF-16le,那么它必须是UTF-16be。
    • 如果该文件包含在使用UTF-16BE解码非字符,那么它必须是UTF-16LE。
    • 如果文件在使用UTF-16le解码时包含非字符,则它必须是UTF-16be。
  2. U + 0A00当前未分配,但U + 000A(LINE FEED)非常常见。
    U + 0D00当前未分配,但U + 000D(CARRIAGE RETURN)非常常见。
    • 如果该文件包含0A 000D 00,那么它可能是UTF-16le。
    • 如果该文件包含00 0A00 0D,那么它可能是UTF-16be。
    • 如果该文件包含在使用UTF-16BE解码未分配的角色,那么它可能是UTF-16LE。
    • 如果文件在使用UTF-16le解码时包含未分配的字符,那么它可能是UTF-16be。
  3. 启发式基于文件格式的知识。 (Example
  4. 的文件可能包含比字符数字更ASCII字符U + XX00
    • 如果文件中包含许多xx 00和几个00 xx,那么它可能是UTF-16LE。
    • 如果该文件包含许多00 xx和几个xx 00,那么它可能是UTF-16be。

注:

  • #4,#5说: “它可能”,而不是 “它必须是” 因为你们今天未分配的可分配的明天。
  • #3包括#1,但#1是一个便宜的测试。
  • #5包括#4,但是#4几乎与#5一样可靠,没有保留随时间变化的未分配字符的长列表。

你可以使用:raw文件中发出声音,执行部分或全部就可以了上述测试,以确定编码,然后使用decodes/\r\n/\n/g

+0

您能否解释(解码)4,5,6的启发式值(原因)? – xxfelixxx

+0

改进了列表。 (数字已经改变。)添加了解释。 – ikegami