Как я могу декодировать данные UTF-16 в Perl, когда я не знаю порядок байтов? - PullRequest
7 голосов
/ 22 мая 2010

Если я открою файл (и укажу кодировку напрямую):

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

Ответы [ 3 ]

12 голосов
/ 22 мая 2010

Если вы просто укажете «UTF-16», Perl будет искать метку порядка байтов (BOM), чтобы выяснить, как ее анализировать.Если нет спецификации, она взорвется.В этом случае вы должны указать Encode, какой у вас порядок байтов, указав либо «UTF-16LE» для little-endian, либо «UTF-16BE» для big-endian.

Есть что-то еще, что происходит сВаша ситуация, хотя, но трудно сказать, не видя данных, которые у вас есть в файле.Я получаю одинаковую ошибку с обоими фрагментами.Если у меня нет спецификации и я не указываю порядок байтов, мой 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) 
    }
5 голосов
/ 22 мая 2010

Вам нужно указать UTF-16BE или UTF-16LE.Смотри http://perldoc.perl.org/Encode/Unicode.html#Size%2c-Endianness%2c-and-BOM

1 голос
/ 22 мая 2010

То, что вы пытаетесь сделать, невозможно.

Вы читаете строки текста без указания кодировки, поэтому каждый байт, содержащий символ новой строки (по умолчанию \x0a), заканчивается строкой. Но этот символ новой строки вполне может быть в середине символа UTF-16, и в этом случае ваша следующая строка не может быть декодирована. Если ваши данные UTF-16LE, это будет происходить все время - перевод строки \x0a \x00. Если у вас UTF16-BE, вам может повезти (новые строки \x00 \x0a), пока вы не получите символ с \x0a в старшем байте.

Итак, не делайте этого, откройте файл в правильной кодировке.

...