Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Системное программирование > как раскодировать cp1251 из Unicode (SMS)


Автор: kain76 3.7.2007, 01:37
Добрый день.
Не могу разобраться с Encode
вытаскиваю тело СМС-сообщения из GSM-модема и дальше при выводе тела в файл или в ст.выход вижу собщение
"Wide character in subroutine entry at C:/Perl/lib/Encode.pm line 182, <DATA> line 164."...  ну и выводит естественно всякую билиберду и символов в ней, естественно, ровно в 2 раза больше, чем в отправленном на модем смс-сообщении.
Сразу говорю что это под WinXP (ActivePerl 5.8).
Я установил все примочки для Encode и далее не могу понять как этим пользоваться. В конечном итоге нужно раскодировать Unicode (UCS-2) в cp1251. 
Буду благодарен за кусок кода  smile 
smile

Автор: nitr 3.7.2007, 08:24
Цитата(kain76 @  3.7.2007,  01:37 Найти цитируемый пост)
Я установил все примочки для Encode

это какие? Он и в своём "изначальном" виде прекрасный инструмент...

Вы или процитируйте сообщение, или вложите файл, который надо "раскодировать" ;)

Добавлено через 2 минуты и 34 секунды
тут слишком много раз обсуждалось - так что можете воспользоваться "Поиском" на форуме, думаю достаточно ввести Encode

Ещё есть неплохая фича вот по этому адресу (она кстати, выводится уже при создании темы, чтобы могли сразу найти ответ, вдруг вопрос поднимался уже) смотреть тут - 
http://forum.vingrad.ru/forum/topic-161775/anchor-entry1183845/0.html#look

Автор: sharq 3.7.2007, 09:11
kain76, функция decode тебе поможет smile

Автор: GoodBoy 3.7.2007, 09:47
Код
use Encode qw(encode decode);

my $str1251 = encode('cp1251', decode('UCS-2', $strUCS2));

Автор: nitr 3.7.2007, 10:21
GoodBoysharq, тут слишком много про это говорилось... я бы сказал больше, но сам уже "тыщу" раз отвечал... пусть научится пользоваться поиском, он ведь рабочий ;)

Автор: kain76 4.7.2007, 04:47
Я искал на форуме и видел здесь эту фичу, но в этих темах конкретно не упоминали про то, как избавиться от лишних (не буквенных) данных в строке. Я так понимаю, что строка, которую я упомянул выводится именно из-за присутствия "описывающих" байтов, которые не декодируются.. Где-то в доках на CPAN я находил что-то об этом, но не могу найти снова. Вот и думал может кто подскажет как от них избавиться.. Encode в поиске ничего толкового не дал

Автор: nitr 4.7.2007, 11:15
Цитата(kain76 @  4.7.2007,  04:47 Найти цитируемый пост)
Я так понимаю, что строка, которую я упомянул выводится именно из-за присутствия "описывающих" байтов

неправильно понял, они все такие, а точнее вы неверно используете Encode, ещё более точно кодировку smile

Ещё раз повторю: http://forum.vingrad.ru/index.php?showtopic=161775&view=findpost&p=1183963

Сам вывел поиск, есть там... Вам уже подсказил - Encode::decode

P.S.: Вы приведите пример текста!!! И будет вам счастье...

Автор: kain76 5.7.2007, 00:30
вот как я пытаюсь это вывести:

########################
use Device::Gsm;
use Encode qw(encode decode);

my $mystr;

  my $gsm = new Device::Gsm( port => 'COM3', pin => '' );
  if( $gsm->connect() ) {
      print "connected!\n";
  } else {
      print "sorry, no connection with gsm phone on serial port!\n";
  }

  # Get list of Device::Gsm::Sms message objects
  # see `examples/read_messages.pl' for all the details
  
  my @messages = $gsm->messages();

#     II. Recieving messages

open(FILE, ">>SMS.txt");
for( $gsm->messages('SM') )
    {   
     print FILE $_->content(), " : ", $_->sender(), "\n";
     $cont=$_->content();
     $mystr = encode('cp1251', decode('UCS-2', $cont));
     print FILE "$mystr";
    } 
close (FILE);
###############################

сам текст оттуда выколупывает Device::Gsm и мне он в первой строке возвращается в таком виде " Р_С_С%РёС' : +79098316102 " (кодировке винды), а вторая строка вообще отсутствует. Сам текст в SMS по идее - "Оущит" (был с похмелья:)

так вот в итоге  ругается так:

Wide character in print at C:\Perl\scripts\1.pl line 38, <DATA> line 164.
Wide character in subroutine entry at C:/Perl/lib/Encode.pm line 162, <DATA> line 164.

Первая строка записывается в файл, а вторая - пустая.
Такие дела. Как бороться?

Автор: nitr 5.7.2007, 11:59
верно так, т.к. utf8
Код

encode('cp1251',decode('utf8', $cont));

Автор: kain76 5.7.2007, 23:59
nitr, поменял на utf8.. теперь так говорит

Wide character in print at C:\Perl\scripts\1.pl line 38, <DATA> line 164.
Cannot decode string with wide characters at C:/Perl/lib/Encode.pm line 162, <DATA> line 164.

А вобще я читал, что SMS-сообщения передаются и хранятся в кодировке UCS-2.. тока там не уточняется LE или BE.. собственно я разницы не знаю, знаю только что их две.

Автор: nitr 6.7.2007, 00:11
kain76, тогда стоит вложить файл с текстом сообщения smile - Не знаю где вы чего читали, но я работал с этим и знаю, что мои были utf8 и НИЧЕГО ДРУГОГО... smile

Даже если то что вы привели - 
Цитата
" Р_С_С%РёС' : +79098316102 " (кодировке винды),
 очень на то похоже!
 можно проверить тупо:
Код

#!perl
use strict;
use warnings;
use Encode 'decode', 'encode';

my $str = 'Оущит';
my $ostr = 'Оущит';
print $str."\n";
print "\n".decode('cp1251', $ostr);

результат
Цитата

Оущит
Оущит


А unicode выведет - угадайте?! Конечно в "китайской или иной" - короче иероглифы, самые настоящие...

Добавлено через 12 минут и 40 секунд
какая ОС? smile

Автор: kain76 6.7.2007, 06:40
Я писАл в первом сообщении: "Сразу говорю что это под WinXP (ActivePerl 5.8)"

Вложить какой файл? с каким сообщением? smile я же говорю, что беру тело сообщения, которое хранится на сим-карте в модеме.

вот это вот сработало (действительно в utf8.. собсно чего я и хотел узнатьsmile):

for( $gsm->messages('SM') )
    {   
     $cont=$_->content();
     $mystr = encode('cp1251', $cont);
     print FILE "$mystr\n";
    } 

но блин всё равно ругается на "Wide characters"
Вобщем, всем большое спасибо. Буду знать теперь куда обратиться.

Автор: nitr 6.7.2007, 07:25
kain76, просто у вас странно приведён пример сообщения, вот и запутали с ОС.

А как можно, как пример ниже, (плюньте временно на "Wide... "), а прикрепите полученный файл content.txt к сообщению на форуме...
Код

for( $gsm->messages('SM') ) {   
    $cont=$_->content();
    open my $flh, '>> content.txt';
    print $flh $cont."\n\n";
    close $flh;
    ...


Будет сподручнее помогать ;) Тем более кроме меня тут много людей, кто сможет помочь...

Автор: kain76 9.7.2007, 00:59
понятно, я просто не думал что кто-то будет ковырять контент, чтобы выяснить какая кодировка smile
прикрепил файл с телом одного сообщения.. в оригинале текст - "Приз". может быть удастся выяснить что там за символы загадочные
Только открывайте не в виндовых приложениях, потому что они автоматом перекодируют содержание

Автор: nitr 9.7.2007, 01:24
kain76, пока непонятно почему вы игнорируете ответы выше smile , т.к. снова привожу код, который выводит "Приз" smile
Код
#!/usr/bin/perl
use Encode 'decode', 'encode';

open my $flh, '<SMS.txt';
local $/;
my $content = <$flh>;
close $flh;
print "Content-type: text/html\n\n";
print encode('cp1251', decode('utf8', $content));


Ваше сообщение в кодировке utf8, данный скрипт переводит в кодировку cp1251, так что не вижу чего-то уж неверного или нерабочего?!

можно в Виндовой "консоле" smile
Код
#!/usr/bin/perl
use Encode 'decode', 'encode';

open my $flh, '<SMS.txt';
local $/;
my $content = <$flh>;
close $flh;
print encode('cp866', decode('utf8', $content));

Цитата
C:\Documents and Settings\nitr>sample.pl
Приз



Цитата(kain76 @  9.7.2007,  00:59 Найти цитируемый пост)
понятно, я просто не думал что кто-то будет ковырять контент, чтобы выяснить какая кодировка smile

Это из-за того, что вы утверждаете, будто бы не работает smile

Думаю ошибка уже кроется дальше... в выводе "ГОТОВОГО" сообщения... Куда вы его выводите, в какой вид или в какой кодировке? ;)

Добавлено @ 01:18
Поэтому (код уж очень похож на прежние ответы из других похожих тем) я "советовал пользоваться поиском", т.к. такую проблему уже решали ни один раз... ;)

Автор: kain76 9.7.2007, 04:02
nitr, да я ничего не игнорирую :) я уже ведь написАл, что всё заработало, только ругается на какие-то символы.
насчёт:
Цитата(nitr @  9.7.2007,  01:24 Найти цитируемый пост)
Куда вы его выводите, в какой вид или в какой кодировке? ;)

видимо, я просто не пойму чего я не упомянул в ситуации :-))
я ведь и кусок кода привёл, где видно, что я записываю это в файл "SMS.txt".. так вот всё туда уже записывается в нужном виде (при просмотре файла в кодировке cp1251 я вижу слово "Приз"), но при этом не забыват поругаться на "Wide characters...".

Теперь другой случай. Тупо не могу перекодировать строку "Здравствуй ворлд!" (редактирую в Far'е в кодировке Win) обратно в utf8, чтобы отослать сообщение.. Приходит в SMS какая-то абракадабра, хотя количество символов соответствует исходящему..

уже как только ни пробовал.. подскажите как правильно написАть, пожалуйста.


Автор: nitr 9.7.2007, 09:57
Цитата(kain76 @  9.7.2007,  04:02 Найти цитируемый пост)
 в нужном виде (при просмотре файла в кодировке cp1251 я вижу слово "Приз"), но при этом не забыват поругаться на "Wide characters...".

для этого я и просил показать само сообщение в её исходной кодировке...

Добавлено через 46 секунд
Цитата(kain76 @  9.7.2007,  04:02 Найти цитируемый пост)
Приходит в SMS какая-то абракадабра, хотя количество символов соответствует исходящему..

проверяйте кодировку...

Добавлено через 1 минуту и 26 секунд
похоже вы В ЦЕЛОМ не разобрались с кодировками и модулем Encode (decode encode)

Автор: kain76 9.7.2007, 23:58
Цитата(nitr @  9.7.2007,  09:57 Найти цитируемый пост)
для этого я и просил показать само сообщение в её исходной кодировке...

Я не могу этого сделать.. Просто не знаю как. Это делает Device::Gsm методом content() при передаче ему ссылки на массив сообщения. Как это происходит я не разбирался. Как это выглядит в файле при выводе выводе обработанной ссылки в переменную, а переменной в файл я показывал.
Цитата(nitr @  9.7.2007,  09:57 Найти цитируемый пост)
проверяйте кодировку...

Добавлено через 1 минуту и 26 секунд
похоже вы В ЦЕЛОМ не разобрались с кодировками и модулем Encode (decode encode) 

Ну, наконец-то, Вы поняли в чём проблема :) Так и есть. Стал бы я обращаться сюда, если бы смог разобраться сам? :)

Автор: nitr 10.7.2007, 00:15
Чтобы разобраться в модуле Encode, почитайте документацию, потестируйте. Вам, думаю, поможет "метод тыка"/"метод проб и ошибок"/"метод подбора", т.к. основные кодировки на глаз не определяете, и простые "ошибки" - 
Цитата(kain76 @  9.7.2007,  04:02 Найти цитируемый пост)
Приходит в SMS какая-то абракадабра
тоже. Вам не поможет в этом форум, только вы сами...
Так что, Perl "в руки", и пробуйте, пробуйте, пробуйте...

smile
Цитата
МЕТОД ТЫКА - метод, основанный на использовании недостаточно достоверных или неполных данных для получения научных или практических выводов. Впервые был применен выдающимся немецким математиком и врачом Гансом Фридрихом Тыком (род. около 1317 г. до н.э., по другим источникам - в 523 г. н.э.), производившим вскрытие Буриданова осла для объяснения причин его смерти. Впоследствии метод и был назван по фамилии ученого. 

Метод Тыка позволяет получить практические результаты во многих областях человеческой деятельности даже при полном отсутствии какой-либо информации для научного анализа. Метод состоит в совершении разных действий, которые теоретически могут привести к нужному результату. Метод бывает двух видов - метод научного тыка и метод ненаучного тыка (другое название метода ненаучного тыка - метод проб и ошибок). Разделение этих видов достаточно условно и применяется только постфактум. Если задача решена успешно, значит, она решалась с помощью метода научного тыка, а если задача не решена - применялся метод проб и ошибок.



Автор: Anarki 10.7.2007, 10:12
Просто надо использовать encode_utf8 вначале
$stroka в utf8 и содержит всякие wide characters
Код

my $octets = encode_utf8($stroka);
from_to($octets, "utf8", "cp1251");
print $octets;

Автор: nitr 10.7.2007, 11:09
Anarki, я ему об этом уже много раз писал... А если гляните в модуль Encode.pm (не знаю удивитесь или нет) ваша функция аналогична тем, что уже обсуждались...

Anarki, плохие методы вы ему советуете, поиском на форуме можно найти тему, в которой как раз и обсуждали оное - вывод: использовать encodedecode.

Автор: Anarki 10.7.2007, 12:20
Цитата(nitr @ 10.7.2007,  14:09)
Anarki, я ему об этом уже много раз писал... А если гляните в модуль Encode.pm (не знаю удивитесь или нет) ваша функция аналогична тем, что уже обсуждались...

Anarki, плохие методы вы ему советуете, поиском на форуме можно найти тему, в которой как раз и обсуждали оное - вывод: использовать encodedecode.

Чем плоха? ВЫ указывали ему искать методом тыка, т.к наверное и не решали подобную проблему!

Цитата

$octets = encode_utf8($string); 

Equivalent to $octets = encode("utf8", $string); The characters that comprise $string are encoded in Perl's internal format and the result is returned as a sequence of octets. All possible characters have a UTF-8 representation so this function cannot fail.

Автор: nitr 10.7.2007, 13:11
smile

Цитата(Anarki @  10.7.2007,  12:20 Найти цитируемый пост)
Чем плоха? ВЫ указывали ему искать методом тыка, т.к наверное и не решали подобную проблему!

всю тему перечитайте... Ничем неплоха, просто другой способ всех "здешних" ответов...

А ему поможет, только "самообучение"/"тестирование", т.е. ему надо разобраться с этим + его смс "в абракадабре" (результат неверно выбранной кодировки).

Автор: nitr 11.7.2007, 02:01
kain76, только что протестил:
Код

...
use Encode 'decode', 'encode';
...

for ( $gsm->messages('SM') ) {   
     $cont = $_->content();
     $mystr = encode('cp1251', $cont);
     print FILE "$mystr\n";

не ругается... 

а обратно -
Код

$sms = decode('cp1251', $mystr);

и "читабельно"...

Автор: kain76 11.7.2007, 04:46
Цитата(nitr @  11.7.2007,  02:01 Найти цитируемый пост)

use Encode 'decode', 'encode';
...

for ( $gsm->messages('SM') ) {   
     $cont = $_->content();
     $mystr = encode('cp1251', $cont);
     print FILE "$mystr\n";


да, всё работает сейчас нормально (в сторону cp1251)

Цитата(nitr @  11.7.2007,  02:01 Найти цитируемый пост)
а обратно -

код Perl
1:

$sms = decode('cp1251', $mystr);

и "читабельно"... 



пробовал.. в смс всё равно приходит ерунда :(

просто я сильно ограничен во времени с этой задачей.. поэтому и обратился. сделал пока транслитом.. буду ковырять

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