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