Как я могу декодировать данные 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
?
EDIT: вот первые несколько байтов:
FF FE 3C 00 68 00 74 00
3 ответов
Если вы просто укажете "UTF-16", Perl будет искать метку порядка байтов (BOM), чтобы выяснить, как ее анализировать. Если нет бомбы, она взорвется. В этом случае вы должны сообщить, какой порядок байтов у вас есть, указав "UTF-16LE" для little-endian или "UTF-16BE" для big-endian.
в вашей ситуации происходит что-то еще, но трудно сказать, не видя данных, которые у вас есть в файле. Я получаю ту же ошибку с обоими фрагментами. Если у меня нет спецификации, и я не указываю порядок байтов, мой Perl жалуется в любом случае. Какой Perl вы используете и какая платформа у вас есть? Имеет ли ваша платформа собственную endianness вашего файла? Я думаю, что поведение, которое я вижу, правильно в соответствии с документами.
кроме того, вы не можете просто прочитать строку в неизвестной кодировке (независимо от значения по умолчанию 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#Size%2c-Endianness%2c-and-BOM
то, что вы пытаетесь сделать невозможно.
Вы читаете строки текста без указания кодировки, поэтому каждый байт, содержащий символ новой строки (по умолчанию \x0a
) концах линии. Но этот символ новой строки может быть в середине символа UTF-16, и в этом случае ваша следующая строка не может быть декодирована.
Если ваши данные UTF-16LE, это произойдет все каналы временной линии \x0a \x00
. Если у вас есть UTF16-BE, вам может повезти (новые строки \x00 \x0a
), пока вы не получите символ с \x0a
в старшем байте.
итак, не делайте этого, откройте файл в правильной кодировке.