У меня есть интересные результаты, пытающиеся разглядеть различия между использованием Encode::decode("utf8", $var)
и utf8::decode($var)
. Я уже обнаружил, что вызов прежнего многократного значения переменной приведет к ошибке «Невозможно декодировать строку с широкими символами в ...», тогда как последний метод будет работать так много раз, как вам нужно, просто вернув false.Perl: utf8 :: decode vs. Encode :: decode
У меня возникли проблемы с пониманием того, как функция length
возвращает разные результаты в зависимости от того, какой метод вы используете для декодирования. Проблема возникает из-за того, что я имею дело с «дважды закодированным» текстом utf8 из внешнего файла. Чтобы продемонстрировать эту проблему, я создал текстовый файл test.txt со следующими символами Unicode в одной строке: U + 00e8, U + 00ab, U + 0086, U + 000a. Эти символы Юникода представляют собой двойное кодирование символов Unicode U + 8acb вместе с символом новой строки. Файл был закодирован на диск в UTF8. Затем я запускаю следующий PERL скрипт:
#!/usr/bin/perl
use strict;
use warnings;
require "Encode.pm";
require "utf8.pm";
open FILE, "test.txt" or die $!;
my @lines = <FILE>;
my $test = $lines[0];
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
my @unicode = (unpack('U*', $test));
print "Unicode:\[email protected]\n";
my @hex = (unpack('H*', $test));
print "Hex:\[email protected]\n";
print "==============\n";
$test = Encode::decode("utf8", $test);
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
@unicode = (unpack('U*', $test));
print "Unicode:\[email protected]\n";
@hex = (unpack('H*', $test));
print "Hex:\[email protected]\n";
print "==============\n";
$test = Encode::decode("utf8", $test);
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
@unicode = (unpack('U*', $test));
print "Unicode:\[email protected]\n";
@hex = (unpack('H*', $test));
print "Hex:\[email protected]\n";
Это дает следующий результат:
Length: 7 utf8 flag: Unicode: 195 168 194 171 194 139 10 Hex: c3a8c2abc28b0a ============== Length: 4 utf8 flag: 1 Unicode: 232 171 139 10 Hex: c3a8c2abc28b0a ============== Length: 2 utf8 flag: 1 Unicode: 35531 10 Hex: e8ab8b0a
Это то, что я хотел бы ожидать. Длина изначально 7, потому что perl считает, что $ test - это всего лишь серия байтов. После декодирования один раз perl знает, что $ test - это серия символов, кодированных utf8 (т. Е. Вместо того, чтобы возвращать длину 7 байт, perl возвращает длину 4 символа, хотя $ test по-прежнему остается 7 байтами в памяти). После второго декодирования $ test содержит 4 байта, которые интерпретируются как 2 символа, чего я ожидаю, так как Encode :: decode взял 4 кодовых пункта и интерпретировал их как байты, закодированные в utf8, в результате получилось 2 символа. Странно, когда я изменяю код для вызова utf8 :: decode вместо (замените все $ test = Encode :: decode («utf8», $ test), с utf8 :: decode ($ test))
Это дает почти идентичный выход, только результат длины отличается:
Length: 7 utf8 flag: Unicode: 195 168 194 171 194 139 10 Hex: c3a8c2abc28b0a ============== Length: 4 utf8 flag: 1 Unicode: 232 171 139 10 Hex: c3a8c2abc28b0a ============== Length: 4 utf8 flag: 1 Unicode: 35531 10 Hex: e8ab8b0a
Похоже, Perl первый подсчитывает байты перед декодированием (как и ожидалось), а затем подсчитывает символы после первого декодирования, но затем подсчитывает байты снова после того, как второе декодирование (не ожидалось). Почему этот переключатель произойдет? Происходит ли в моем понимании, как работают эти функции декодирования?
Спасибо,
Matt
Любая причина, по которой вы «требуете» модули вместо того, чтобы «использовать» их? – 2010-12-02 21:08:50
Я не сделал
use
utf8, потому что это так говорит perl, что ваш код сам utf8-encoded, который мне не нужен (http://perldoc.perl.org/utf8.html). Полагаю, я мог быuse
d Кодировать, но я просто не мог этого сделать. – Matt 2010-12-02 21:41:36