如果文件被写为小端或大端,如何检入perl?

Pra*_*eep 4 perl encoding endianness utf-16le

实际上我必须解析一些可以是任何形式的endian(Big或Little)的文件.如果我使用一个编码并解析其他编码,Perl解释器就会死掉.

open (my $fh, "<:raw:encoding(UTF-16LE):crlf", $ARGV[0]) or die cannot open file for reading : $! \n";
Run Code Online (Sandbox Code Playgroud)

要么

open (my $fh, "<:raw:encoding(UTF-16BE):crlf", $ARGV[0]) or die cannot open file for reading : $! \n";
Run Code Online (Sandbox Code Playgroud)

输出(对于LE中的文件和perl的编码为BE)

UTF-16BE:Malformed HI surrogate dc00 at toASCII.pl line 123.
Run Code Online (Sandbox Code Playgroud)

ike*_*ami 5

大多数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. 基于文件格式知识的启发式算法.(例子)
  4. 文件可能包含比字符数U + xx00更多的ASCII字符
    • 如果文件包含很多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.