Как я могу декодировать данные 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
7
задан Geo 22 May 2010 в 16:33
поделиться

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) 
    }
12
ответ дан 6 December 2019 в 10:48
поделиться

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

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

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

1
ответ дан 6 December 2019 в 10:48
поделиться

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

5
ответ дан 6 December 2019 в 10:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: