Как я могу декодировать данные UTF-16 в Perl, когда я не знаю порядок байтов?
Если я открою файл (и укажу кодировку напрямую):
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 ответа
Если вы просто укажете "UTF-16", Perl будет искать метку порядка байтов (BOM), чтобы выяснить, как ее анализировать. Если нет спецификации, она взорвется. В этом случае вы должны указать Encode, какой у вас порядок байтов, указав либо "UTF-16LE" для младшего байта, либо "UTF-16BE" для старшего байта.
Хотя с вашей ситуацией происходит что-то еще, но трудно сказать, не увидев данных, которые есть в файле. Я получаю одинаковую ошибку с обоими фрагментами. Если у меня нет спецификации и я не указываю порядок байтов, мой 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)
}
Вам нужно указать либо UTF-16BE, либо UTF-16LE. См. http://perldoc.perl.org/Encode/Unicode.html
То, что вы пытаетесь сделать, невозможно.
Вы читаете строки текста без указания кодировки, поэтому каждый байт, содержащий символ новой строки (по умолчанию \x0a
) заканчивает строку. Но этот символ новой строки вполне может быть в середине символа UTF-16, и в этом случае ваша следующая строка не может быть декодирована. Если ваши данные UTF-16LE, это будет происходить все время - перевод строки \x0a \x00
, Если у вас есть UTF16-BE, вам может повезти (\x00 \x0a
), пока не получится персонаж с \x0a
в старшем байте.
Так что не делайте этого, откройте файл в правильной кодировке.