Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Перевод строки из кодировки в кодировку  (Прочитано 17950 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Tenzor
Интересующийся

ru
Offline Offline

« : 03-09-2012 08:42 » 

Здравствуйте. Получаю строку из БД Paradox
(как получаю можно посмотреть тут https://forum.shelek.ru/index.php/topic,28894.0.html)

Выводится кракозябрами. В BDE-ADMINISTRATOR стоит DB866RU0. Тип данных получаемые из таблицы определяется как 202, т.е. NVarChar. Получаю в строку типа _bstr_t. Для перевода в CP1251 написал такой код с использованием iconv.
Получение строки
Код: (C++)
   _bstr_t strValue = pRst->Fields->Item[(_variant_t)index]->Value;
   char *pp=_com_util::ConvertBSTRToString(strValue.GetBSTR());
  Decoders(pp);

Код: (C++)
BOOL Decoders(const char *src){
        setlocale(LC_ALL, "rus");
        size_t str_len = strlen(src), out_len =str_len;
        char *piout;
        char *op;
        piout=new char[out_len];
        op=piout;
        iconv_t cd = iconv_open("CP866", "CP1251");
        size_t k=iconv(cd, &src, &str_len, &op, &out_len);
        if(k==-1){cout<<"Fail"<<endl;iconv_close(cd);return 0;}
        cout<<"Out: ";
         for(int u=0;u<out_len;u++)cout<<piout[u];
         cout<<endl;
         delete [] out;
         iconv_close(cd);
        return 1;
}      
Пытаюсь в Decoders перекодировать из 866 в 1215, но возвращается 0, т.е. перекодируется 0 байт -> это уже не 866 (так как если бы была ошибка вернулось бы -1).В редакторе far manger по нажатию F8 (т.е. перевод из DOS (866) в Win(1251)) все названия на русском отлично отображаются. Есть подозрения, что из-за того, что данные считываются в юникодную строку, текст перекодируется во что-то неизвестное. пытался использовать cast и другие функции конвертации из юникода в строку. Помогите разобраться, пожалуйста.

iconv брал отсюда http://gnuwin32.sourceforge.net/packages/libiconv.htm
« Последнее редактирование: 03-09-2012 08:47 от Tenzor » Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 03-09-2012 09:57 » 

Tenzor, а где и как считывается в юникодную строку? Текст перекодируется в unicode, или как?
Если строка именно юникодная и где-то "в лоб" приводится к char - то проблемы там обязательно будут. Перекодирование 0 байт указывает на то, что, возможно, первый символ строки - нулевой (что, в принципе, похоже на приведение wchar_t * к char *). Поэтому я бы проверил, какова длина преобразуемой строки и её содержимое. На большее телепатических способностей не хватает.
Записан
Tenzor
Интересующийся

ru
Offline Offline

« Ответ #2 : 03-09-2012 14:21 » 

Текст берется из пардоксовского db файла.
Текст сохраняется в _bstr_t строке
Код: (C++)
 _bstr_t strValue = pRst->Fields->Item[(_variant_t)index]->Value;
Т.е. CP866 строка сохраняется в юникодной и видимо здесь и есть проблема.
Длины одинаковые до и после перекодировки
Попробовал перекодировать так: Символы изменились в исходной и полученной строке, но толку то
Код: (C++)
char *pp;
pp=static_cast<const char *>(strValue);

Попробовал через stream с помощью GetCharset посмотреть кодировку. Выдает 0, т.е. ANSI (United States, Western Europe).

Накидал на VB. Переводит. осталось понять как это в С++ перенести

Код: (Visual Basic)
Private Sub Form_Load()
    Set Conn = CreateObject("ADODB.Connection")
    ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Lisega;Extended Properties=Paradox 5.x;"
    Conn.CursorLocation = adUseClient
    Conn.Open ConnectionString
    Dim i As Integer
    Set rs = Conn.Execute("SELECT K_FREE_HG_TEXT1 FROM KONSTZ8.DB")
    Dim str As String, dest As String
    str = rs.Fields(0)
    dest = ChangeTextCharset(str, "Windows-1251", "iso8859-1")
    MsgBox dest
    rs.Close
    Conn.Close
End Sub

Function ChangeTextCharset(ByVal txt$, ByVal DestCharset$, Optional ByVal SourceCharset$) As String
    On Error Resume Next: Err.Clear
     With CreateObject("ADODB.Stream")
         .Type = 2: .Mode = 3
         If Len(SourceCharset$) Then .Charset = SourceCharset$
        .Open
         .WriteText txt$
         .Position = 0
         .Charset = DestCharset$
        ChangeTextCharset = .ReadText
         .Close
     End With
End Function
 

* PRJINF812.DB (7.73 Кб - загружено 1031 раз.)
« Последнее редактирование: 03-09-2012 14:28 от Tenzor » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 05-09-2012 08:47 » 

а в VB всегда юникод - так что Вад прав Улыбаюсь

Код:
std::wstring str=reinterpret_cast<const wchar_t*>(strValue);
Записан

Tenzor
Интересующийся

ru
Offline Offline

« Ответ #4 : 10-09-2012 11:26 » 

Сорри, не мог добраться до компа несколько дней)) решил так
Код: (C++)
_bstr_t strValue = pRst->Fields->Item[(_variant_t)index]->Value;
_StreamPtr strm=NULL;
strm.CreateInstance(__uuidof(Stream));
strm->Charset="iso8859-1";
CComVariant vtMissing(DISP_E_PARAMNOTFOUND,VT_ERROR);
strm->Open(vtMissing,adModeUnknown,adOpenStreamUnspecified,L"",L"");
strm->WriteText(strValue,adWriteChar);
strm->Position=0;
strm->Charset="Windows-1251";
int nums=strValue.length();
t=(char *)strm->ReadText(nums);
strm->Close();
cout<<"t: "<<t<<endl;

Всем спасибо за помощь)
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 10-09-2012 17:18 » 

Алексей1153++, ты уверен в reinterpret_cast? Такое сильное преобразование типов стоит использовать только в самых крайних случаях.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 11-09-2012 14:55 » 

Dimka, не стал уж писать (const wchar_t*) ... , чтобы не вызывать стонов знатоков ))  Лично я бы так и сделал
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 11-09-2012 15:22 » 

Алексей1153++, я "застонал" именно потому, что то, что ты написал, как раз и есть то же самое, что ты решил не писать Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 12-09-2012 16:46 » new

Dimka, ну раз оно там так и есть, куда от этого денешься
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines