2016-12-15 6 views
4

На самом деле я должен разбирать некоторые файлы, которые могут быть в любом виде endian (Big или Little). Perl-интерпретатор умирает, если я использую одну кодировку и разбираю другую.Как проверить perl, если файл написан как маленький 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] (http://stackoverflow.com/questions/2610849/finding-if-the-system-is-little-endian-or-big -endian-with-perl) –

+2

@EliSadoff Этот вопрос задает вопрос, как определить, является ли конкретный * файл * большим или маленьким, а не системой. – ThisSuitIsBlackNot

+2

Почему «мои $ 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

Не тестируйте '$ @', возвращайте 1 из 'eval' и проверяйте возвращаемое значение. – 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 00 или 0D 00, то это, вероятно, UTF-16le.
    • Если файл содержит 00 0A или 00 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 говорят, "это, вероятно," вместо "это должно быть", потому что Unassigned сегодня может быть назначено завтра.
  • # 3 включает # 1, но # 1 - дешевый тест.
  • # 5 содержит # 4, но # 4 почти так же надежен, как и # 5, не сохраняя длинный список неназначенных символов, которые со временем меняются.

Вы можете чавкать в файл с помощью :raw, выполнять некоторые или все из перечисленных выше тестов на нем, чтобы определить кодировку, а затем использовать decode и s/\r\n/\n/g.

+0

Не могли бы вы объяснить (декодировать) значения эвристики (причина) для 4,5,6? – xxfelixxx

+0

Улучшен список. (Номера изменены.) Добавлены пояснения. – ikegami