Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > трабл с Encode и utf


Автор: Зюзе 15.2.2010, 17:40
Здравствуйте уважаемые перловоды и перловодки smile

Буду совсем краток, сейчас пилю малюсенького jabber бота который будет перекодировать переданый ему покоцаный текст в читабельный формат, проблема в том, что сервер насколько я понял передает и принимает сообщения в utf-8

вот пример входящего сообщения:
$message = ' хЧБЦБЕНЩК ЛМЙЕОФ! уРБУЙВП, ЮФП ЧПУРПМШЪПЧБМЙУШ ХУМХЗБНЙ пФ чБУ ОЕ РПУФХРЙМЙ ДЕОЕЦОЩЕ УТЕДУФЧБ ДМС ЪБЮЙУМЕОЙС ПЗМБУОП  ТЕЕУФТХ'

пока допетрил, что к входящим сообщениям надо применить utf8::decode($message) получал отвал Uncaught exception from user code:
        Wide character in subroutine entry at /usr/local/lib/perl5/5.8.9/mach/Encode.pm line 174.

сейчас при print encode('cp1251', $message); выводит читаемое сообщение, т.е:
Код

PRISHLO:\n$VAR1 = " \x{445}\x{427}\x{411}\x{426}\x{411}\x{415}\x{41d}\x{429}\x{41a} \x{41b}\x{41c}\x{419}\x{415}\x{41e}\x{424}!
\x{443}\x{420}\x{411}\x{423}\x{419}\x{412}\x{41f}, \x{42e}\x{424}\x{41f} \x{427}\x{41f}\x{423}\x{420}\x{41f}\x{41c}\x{428}\x{42a}\x{41f}\x{427}\x{411}\x{41c}\x{419}\x{423}\x{428} \x{425}\x{423}\x{41c}\x{425}\x{417}\x{411}\x{41d}\x{419}
\x{43f}\x{424} \x{447}\x{411}\x{423} \x{41e}\x{415} \x{420}\x{41f}\x{423}\x{424}\x{425}\x{420}\x{419}\x{41c}\x{419} \x{414}\x{415}\x{41e}\x{415}\x{426}\x{41e}\x{429}\x{415} \x{423}\x{422}\x{415}\x{414}\x{423}\x{424}\x{427}\x{411} \x{414}\x{41c}\x{421} \x{42a}\x{411}\x{42e}\x{419}\x{423}\x{41c}\x{415}\x{41e}\x{419}\x{421} \x{423}\x{41f}\x{417}\x{41c}\x{411}\x{423}\x{41e}\x{41f}  \x{422}\x{415}\x{415}\x{423}\x{424}\x{422}\x{425}";
 Уважаемый клиент!
Спасибо, что воспользовались услугами
От Вас не поступили денежные средства для зачисления согласно  реестру хЧБЦБЕНЩК ЛМЙЕОФ!
уРБУЙВП, ЮФП ЧПУРПМШЪПЧБМЙУШ ХУМХЗБНЙ
пФ чБУ ОЕ РПУФХРЙМЙ ДЕОЕЦОЩЕ УТЕДУФЧБ ДМС ЪБЮЙУМЕОЙС УПЗМБУОП  ТЕЕУФТХWide character in subroutine entry at /usr/local/lib/perl5/5.8.9/mach/Encode.pm
        line 174 (#2)
    (W utf8) Perl met a wide character (>255) when it wasn't expecting
Uncaught exception from user code:
        Wide character in subroutine entry at /usr/local/lib/perl5/5.8.9/mach/Encode.pm line 174.
 at /usr/local/lib/perl5/5.8.9/mach/Encode.pm line 174


вот кусок бота который принимает, декодирует и отправляет обратно сообщение:
Код

$message = ' хЧБЦБЕНЩК ЛМЙЕОФ! уРБУЙВП, ЮФП ЧПУРПМШЪПЧБМЙУШ ХУМХЗБНЙ пФ чБУ ОЕ РПУФХРЙМЙ ДЕОЕЦОЩЕ УТЕДУФЧБ ДМС ЪБЮЙУМЕОЙС ПЗМБУОП  ТЕЕУФТХ'
print 'PRISHLO:';
utf8::decode($message);
print Dumper($message);
print encode('cp1251', $message);
print encode('koi8-r', $message);
#print Dumper($message);
utf8::encode($message);
print Dumper($message);


но, если я раскомментирую строчку utf8::encode($message) обратно текст приходит вот в таком виде:
Код

хЧБЦБЕНЩК ЛМЙЕОФ! 
уРБУЙВП, ЮФП ЧПУРПМШПЧБМЙУШ ХУМХЗБНЙ
пФ чБУ ОЕ РПУФХРЙМЙ ДЕОЕЦОЩЕ УТЕДУФЧБ ДМС БЮЙУМЕОЙС УПЗМБУОП  Ð¢Ð•ЕУФТХ


подскажите как победить эти кракозябры ?  smile  smile  smile 

Автор: okanatov 15.2.2010, 19:22
А другие способы можно предлагать?
Если есть возможность устанавливать модули, посмотри Convert::Cyrillic. Может он лучше подойдёт?

Автор: sir_nuf_nuf 16.2.2010, 10:02
разберись что тебе приходит по сети.
Как я понимаю должно работать по типу shitirliz ?
т.е. юзер вводит кракозябры, бот их раскодирует и присылает нормальный текст. Так ?

Тогда
а) если джаббер тебе передает данные закодированные в utf8, то прежде всего нужно
my $data = decode('UTF8', $data);
б) если джаббер при передаче не кодирует данные (а просто требует чтобы они были utf8), то хватит
utf8::downgrade($data);
в) после этого у вас есть сырые данные.
вы подбираете кодировку:
$data = guesssss($data);
г) кодируете это обратно в utf8 (что бы джабер мог передавать)
$data = encode('UTF8', $data) 
д) proffit =)

Автор: Зюзе 16.2.2010, 12:45
Цитата(okanatov @ 15.2.2010,  19:22)
А другие способы можно предлагать?
Если есть возможность устанавливать модули, посмотри Convert::Cyrillic. Может он лучше подойдёт?

не хотелось бы дополнительный модуль ставить там где можно обойтись стндартными

Добавлено через 1 минуту
Цитата(sir_nuf_nuf @ 16.2.2010,  10:02)
разберись что тебе приходит по сети.
Как я понимаю должно работать по типу shitirliz ?
т.е. юзер вводит кракозябры, бот их раскодирует и присылает нормальный текст. Так ?

Тогда
а) если джаббер тебе передает данные закодированные в utf8, то прежде всего нужно
my $data = decode('UTF8', $data);
б) если джаббер при передаче не кодирует данные (а просто требует чтобы они были utf8), то хватит
utf8::downgrade($data);
в) после этого у вас есть сырые данные.
вы подбираете кодировку:
$data = guesssss($data);
г) кодируете это обратно в utf8 (что бы джабер мог передавать)
$data = encode('UTF8', $data) 
д) proffit =)

именнно, лабаю замену штирлицу ))) но profit пока не наблюдается  smile 
сейчас после 
Код

$message=encode('utf-8', $message);

в ответ приходит вот что:
Код

хЧБЦБЕНЩК ЛМЙЕОФ! 
уРБУЙВП, ЮФП ЧПУРПМШПЧБМЙУШ ХУМХЗБНЙ
пФ чБУ ОЕ РПУФХРЙМЙ ДЕОЕЦОЩЕ УТЕДУФЧБ ДМС БЮЙУМЕОЙС УПЗМБУОП  Ð¢Ð•ЕУФТХ

дампер выдал:
Код

PRISHLO:\n$VAR1 = "\x{445}\x{427}\x{411}\x{426}\x{411}\x{415}\x{41d}\x{429}\x{41a} \x{41b}\x{41c}\x{419}\x{415}\x{41e}\x{424}!
\x{443}\x{420}\x{411}\x{423}\x{419}\x{412}\x{41f}, \x{42e}\x{424}\x{41f} \x{427}\x{41f}\x{423}\x{420}\x{41f}\x{41c}\x{428}\x{42a}\x{41f}\x{427}\x{411}\x{41c}\x{419}\x{423}\x{428} \x{425}\x{423}\x{41c}\x{425}\x{417}\x{411}\x{41d}\x{419}";
Уважаемый клиент!
Спасибо, что воспользовались услугамихЧБЦБЕНЩК ЛМЙЕОФ!
уРБУЙВП, ЮФП ЧПУРПМШЪПЧБМЙУШ ХУМХЗБНЙ$VAR1 = "\x{445}\x{427}\x{411}\x{426}\x{411}\x{415}\x{41d}\x{429}\x{41a} \x{41b}\x{41c}\x{419}\x{415}\x{41e}\x{424}!
\x{443}\x{420}\x{411}\x{423}\x{419}\x{412}\x{41f}, \x{42e}\x{424}\x{41f} \x{427}\x{41f}\x{423}\x{420}\x{41f}\x{41c}\x{428}\x{42a}\x{41f}\x{427}\x{411}\x{41c}\x{419}\x{423}\x{428} \x{425}\x{423}\x{41c}\x{425}\x{417}\x{411}\x{41d}\x{419}";
$VAR1 = 'я┘пїп▒піп▒п•п²п╘п  п⌡п°п≥п•п·пє!
я┐п═п▒пёп≥п▓п÷, п╝пєп÷ пїп÷пёп═п÷п°п╗п╙п÷пїп▒п°п≥пёп╗ п╔пёп°п╔п≈п▒п²п≥';







Автор: vadiml 17.2.2010, 23:01
jabber всегда работает в utf8.

А по поводу передач -- старайтесь всегда исходить из условия что Вы получаете данные со снятым флагом utf8, и отправлять тоже со снятым, т.е. ставить/снимать флаг надо на границе своего кода.
Если Вы сомневаетесь если ли флаг, используйте utf8::decode() -- эта функция сначала проверяет наличие флага, или сами его проверяйте.
Если Вам нужен utf8, то в своём коде везде используйте с установленным флагом, иначе Вы замаетесь с его проверкой, снятием и установкой.
Если у Вас в коде utf8 не нужна -- избавляйтесь от неё сразу при получении данных.

Можете посмотреть Net::Whois::Raw -- когда я переводил его на utf8 для приёма данных в куче разных кодировок, перепробовал кучу способов, думаю что описанное здесь -- самое оптимальное.

Автор: sir_nuf_nuf 18.2.2010, 10:01
могу еще посоветовать не Data::Dumper а Devel::Peek.

примерно так
Код

use Devel::Peek;
my $str = "bubu";
Dump($str);   #  да, именно Dump, без print.  буде вывод в STDERR


Он показывает какие флаги стоят на скаляре

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)