Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Преобразование Ansi <-> Utf8 
V
    Опции темы
Alca
Дата 23.11.2009, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Надо выполнить преобразование Ansi <-> Utf8. Вот функции:
Код

//---------------------------------------------------------------------------
std::wstring sAnsiToUtf8(const std::string &csAnsiStr) {
    INT iLen = ::MultiByteToWideChar(CP_ACP, 0, csAnsiStr.c_str(), - 1, NULL, 0);
    
    if (iLen > 0) {        
        std::vector<wchar_t> vw(iLen);
        ::MultiByteToWideChar(CP_ACP, 0, csAnsiStr.c_str(), - 1, &vw[0], iLen);
        
        return &vw[0];
    } else {
        return L"";
    }
}
//---------------------------------------------------------------------------
std::string sUtf8ToAnsi(const std::wstring &csUtf8Str) {
    INT iLen = ::WideCharToMultiByte(CP_UTF8, 0, csUtf8Str.c_str(), - 1, NULL, 0, NULL, NULL);
    
    if (iLen > 0) {        
        std::vector<char> vw(iLen);
        ::WideCharToMultiByte(CP_UTF8, 0, csUtf8Str.c_str(), - 1, &vw[0], iLen, NULL, NULL);
        
        return &vw[0];
    } else {
        return "";
    }
}
//---------------------------------------------------------------------------


Тест:
Код

const std::string csAnsiStr = "Это АНСИ-строка...";                  

std::wstring wsRes;  
std::string  sRes;           

wsRes = sAnsiToUtf8(csAnsiStr);        //wsRes содержит "Это АНСИ-строка..."
sRes  = sUtf8ToAnsi(wsRes);            //sRes  содержит "Это АНСИ-строка..."
//
assert(csAnsiStr == sRes);            //валиться assert

Чего не так?


--------------------
PM WWW ICQ Skype Jabber   Вверх
jonie
Дата 23.11.2009, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



Цитата

Код

wsRes = sAnsiToUtf8(csAnsiStr);        //wsRes содержит "Это АНСИ-строка..."

так ведь это не UTF-8, это UCS2 (который урезанный UTF-16LE).
а вы потом хотите его конвертируете в UTF-8 функцией со странным названием "sUtf8ToAnsi".

Т.е. у вас сейчас две функции делают вот что: ANSI->UCS-2->UTF-8


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Alca
Дата 23.11.2009, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Как правильно? Можно пример кода?


--------------------
PM WWW ICQ Skype Jabber   Вверх
jonie
Дата 23.11.2009, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



Цитата

 Conversion between UTF8 and ANSI codepage using WINAPI
For conversion between ANSI code page and UTF-8 can be used Windows API functions WideCharToMultiByte() and MultiByteToWideChar(). Both ways are very similar as you can see below.
There is only one problem for this method - you are limited to ANSI codepages installed on the system.
Conversion from ANSI to UTF-8

    * convert input ANSI string to widechar using MultiByteToWideChar(CP_ACP, ...) function (CP_ACP is current Windows system Ansi code page)
    * convert output widechar string from previous call to UTF-8 using WideCharToMultiByte(CP_UTF8, ...)  function

Conversion from UTF-8 to ANSI

    * convert input UTF-8 string to widechar using MultiByteToWideChar(CP_UTF8, ...) function
    * convert output widechar string from previous call to ANSI using WideCharToMultiByte(CP_ACP, ...)  function (CP_ACP is current Windows system Ansi code page)
стырено с http://voloda.bazilisek.net/conversion-bet...-a4c/index.html

Сами-то напишите?

кстати, вам не обязательно делать vector, можно использовать std::string::resize() в связке с &string.at(0) ...




--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Alca
Дата 23.11.2009, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Цитата

Сами-то напишите?

Спасибо, попробую. 
Цитата

кстати, вам не обязательно делать vector, можно использовать std::string::resize() в связке с &string.at(0) ...

 smile 


--------------------
PM WWW ICQ Skype Jabber   Вверх
Alca
Дата 23.11.2009, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Попытка №2:
Код

//---------------------------------------------------------------------------
//TODO: - sAnsiToUtf8
/*
convert input ANSI string to widechar using MultiByteToWideChar(CP_ACP, ...) function (CP_ACP is current Windows system Ansi code page)
convert output widechar string from previous call to UTF-8 using WideCharToMultiByte(CP_UTF8, ...)  function
*/

std::wstring sAnsiToUtf8(const std::string &csAnsiStr) {
    CHAR  szUtf  [MAX_PATH] = {0};
    WCHAR wszTemp[MAX_PATH] = {0};

    INT iSize          = 0;
    INT iMultiByteSize = 0;

    iSize           = ::MultiByteToWideChar(CP_ACP,  0, csAnsiStr.c_str(), csAnsiStr.size(), NULL,    0); 
    /*DEBUG*/XASSERT_RET(0 < iSize, std::wstring());
    iSize           = ::MultiByteToWideChar(CP_ACP,  0, csAnsiStr.c_str(), csAnsiStr.size(), wszTemp, iSize);
    /*DEBUG*/XASSERT_RET(0 < iSize, std::wstring());


    iMultiByteSize  = ::WideCharToMultiByte(CP_UTF8, 0, wszTemp, iSize, NULL,  0,              NULL, NULL); 
    /*DEBUG*/XASSERT_RET(0 < iMultiByteSize, std::wstring());

    iMultiByteSize  = ::WideCharToMultiByte(CP_UTF8, 0, wszTemp, iSize, szUtf, iMultiByteSize, NULL, NULL); 
    /*DEBUG*/XASSERT_RET(0 < iMultiByteSize, std::wstring());

    szUtf[iMultiByteSize] = '\0'; 
    return (LPCWSTR)&szUtf[0];

    //return (LPCWSTR) &std::string(szUtf, iMultiByteSize).at(0);
}
//---------------------------------------------------------------------------
//TODO: - sUtf8ToAnsi
/*
convert input UTF-8 string to widechar using MultiByteToWideChar(CP_UTF8, ...) function
convert output widechar string from previous call to ANSI using WideCharToMultiByte(CP_ACP, ...)  function (CP_ACP is current Windows system Ansi code page)
*/
std::string sUtf8ToAnsi(const std::wstring &csUtf8Str) {
    //norm - входная строка
    //utf- выходная
    CHAR  szUtf  [MAX_PATH] = {0};
    WCHAR wszTemp[MAX_PATH] = {0};

    INT iSize          = 0;
    INT iMultiByteSize = 0;

    iSize           = ::MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)csUtf8Str.data(), csUtf8Str.size(), NULL,    0); 
    /*DEBUG*/XASSERT_RET(0 < iSize, std::string());

    iSize           = ::MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)csUtf8Str.data(), csUtf8Str.size(), wszTemp, iSize); 
    /*DEBUG*/XASSERT_RET(0 < iSize, std::string());



    iMultiByteSize  = ::WideCharToMultiByte(CP_ACP,  0, wszTemp, iSize, NULL,  0,              NULL, NULL); 
    /*DEBUG*/XASSERT_RET(0 < iMultiByteSize, std::string());

    iMultiByteSize  = ::WideCharToMultiByte(CP_ACP,  0, wszTemp, iSize, szUtf, iMultiByteSize, NULL, NULL); 
    /*DEBUG*/XASSERT_RET(0 < iMultiByteSize, std::string());

    szUtf[iMultiByteSize] = '\0';
    return std::string(szUtf);        //

    //return std::string(szUtf, iMultiByteSize);
}


Код

        const std::string csAnsiStr = "Это АНСИ-строка...";                  

        std::wstring wsRes;  
        std::string  sRes;           

        wsRes = sAnsiToUtf8(csAnsiStr);           //<<<<<<<< "귐苑뻐퀠킐킝킡⶘臑苑胑뻐뫐냐⸮."
        sRes  = sUtf8ToAnsi(wsRes);                  //<<<<<<<< "Это АНСИ-"
        XASSERT(csAnsiStr == sRes);

строка не поностью конвертиться.... Где косяк?

Это сообщение отредактировал(а) Alca - 23.11.2009, 23:28


--------------------
PM WWW ICQ Skype Jabber   Вверх
586
Дата 24.11.2009, 01:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 39
Всего: 146



Код
#include <windows.h>
#include <tchar.h>
#include <iostream>
std::wstring strtows(const std::string &str, UINT codePage)
{
    std::wstring ws;
    int n = MultiByteToWideChar(codePage, 0, str.c_str(), str.size()+1, /*dst*/NULL, 0);
    if(n)
    {
        ws.resize(n-1);
        if(MultiByteToWideChar(codePage, 0, str.c_str(), str.size()+1, /*dst*/&ws[0], n) == 0)
            ws.clear();
    }
    return ws;
}
std::string wstostr(const std::wstring &ws, UINT codePage)
{
    std::string str;
    int n = WideCharToMultiByte(codePage, 0, ws.c_str(), ws.size()+1, /*dst*/NULL, 0, /*defchr*/0, NULL);
    if(n)
    {
        str.resize(n-1);
        if(WideCharToMultiByte(codePage, 0, ws.c_str(), ws.size()+1, /*dst*/&str[0], n, /*defchr*/0, NULL) == 0)
            str.clear();
    }
    return str;
}
std::string chcp(const std::string &str, UINT codePageSrc, UINT codePageDst)
{
    return wstostr(strtows(str, codePageSrc), codePageDst);
}
int main(int argc, char* argv[])
{
    std::string strAcpSrc = "ANSI строка";
    std::string strUtf = chcp(strAcpSrc, CP_ACP, CP_UTF8);
    std::string strAcp = chcp(strUtf, CP_UTF8, CP_ACP);
    std::cout << ((strAcpSrc == strAcp) ? "success" : "error");
    std::cin.get();
    return 0;
}


Это сообщение отредактировал(а) 586 - 24.11.2009, 11:05
PM   Вверх
Alca
Дата 24.11.2009, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



586, спасибо, работает. 
Я понял, где у меня была ошибка:
Надо было вместо:
Код

std::wstring sAnsiToUtf8(const std::string &csAnsiStr) {
...

написать:
Код

std::string sAnsiToUtf8(const std::string &csAnsiStr) {
...

Вот тоже рабочий код (хотя с буферами нехорошо будет):
Код

//---------------------------------------------------------------------------
//TODO: + sAnsiToUtf8
/*
convert input ANSI string to widechar using MultiByteToWideChar(CP_ACP, ...) function (CP_ACP is current Windows system Ansi code page)
convert output widechar string from previous call to UTF-8 using WideCharToMultiByte(CP_UTF8, ...)  function
*/

std::string sAnsiToUtf8(const std::string &csAnsiStr) {
    CHAR  szUtf  [1024] = {0};
    WCHAR wszTemp[1024] = {0};

    INT iSize          = 0;
    INT iMultiByteSize = 0;

    iSize           = ::MultiByteToWideChar(CP_ACP,  0, csAnsiStr.c_str(), csAnsiStr.size(), NULL,    0); 
    /*DEBUG*/XASSERT_RET(0 < iSize, std::string());
    iSize           = ::MultiByteToWideChar(CP_ACP,  0, csAnsiStr.c_str(), csAnsiStr.size(), wszTemp, iSize);
    /*DEBUG*/XASSERT_RET(0 < iSize, std::string());


    iMultiByteSize  = ::WideCharToMultiByte(CP_UTF8, 0, wszTemp, iSize, NULL,  0,              NULL, NULL); 
    /*DEBUG*/XASSERT_RET(0 < iMultiByteSize, std::string());

    iMultiByteSize  = ::WideCharToMultiByte(CP_UTF8, 0, wszTemp, iSize, szUtf, iMultiByteSize, NULL, NULL); 
    /*DEBUG*/XASSERT_RET(0 < iMultiByteSize, std::string());

    //szUtf[iMultiByteSize] = '\0'; 
    //return (LPCWSTR)&szUtf[0];

    std::string sRes = szUtf;


    //return (LPCWSTR) (& (std::string(szUtf, iMultiByteSize).at(0)));

    return &szUtf[0];
}
//---------------------------------------------------------------------------
//TODO: + sUtf8ToAnsi
/*
convert input UTF-8 string to widechar using MultiByteToWideChar(CP_UTF8, ...) function
convert output widechar string from previous call to ANSI using WideCharToMultiByte(CP_ACP, ...)  function (CP_ACP is current Windows system Ansi code page)
*/
std::string sUtf8ToAnsi(const std::string &csUtf8Str) {
    //norm - входная строка
    //utf- выходная
    CHAR  szUtf  [1024] = {0};
    WCHAR wszTemp[1024] = {0};

    INT iSize          = 0;
    INT iMultiByteSize = 0;

    iSize           = ::MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)csUtf8Str.data(), csUtf8Str.size(), NULL,    0); 
    /*DEBUG*/XASSERT_RET(0 < iSize, std::string());

    iSize           = ::MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)csUtf8Str.data(), csUtf8Str.size(), wszTemp, iSize); 
    /*DEBUG*/XASSERT_RET(0 < iSize, std::string());



    iMultiByteSize  = ::WideCharToMultiByte(CP_ACP,  0, wszTemp, iSize, NULL,  0,              NULL, NULL); 
    /*DEBUG*/XASSERT_RET(0 < iMultiByteSize, std::string());

    iMultiByteSize  = ::WideCharToMultiByte(CP_ACP,  0, wszTemp, iSize, szUtf, iMultiByteSize, NULL, NULL); 
    /*DEBUG*/XASSERT_RET(0 < iMultiByteSize, std::string());

    return std::string(szUtf, iMultiByteSize);
}
//---------------------------------------------------------------------------



--------------------
PM WWW ICQ Skype Jabber   Вверх
Velud
Дата 17.5.2012, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 17.8.2008

Репутация: нет
Всего: нет



а как конвертировать не wide char а обычную однобайтовую?
PM MAIL   Вверх
xvr
Дата 17.5.2012, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(Velud @  17.5.2012,  16:53 Найти цитируемый пост)
а как конвертировать не wide char а обычную однобайтовую? 

- А теперь мы попросим нашего глубокоуважаемого гостя сыграть нам 'Лунную сонату'
- Как, еще раз ?!

PS. Сделайте свою тему - нехорошо реанимировать 3х летний труп  smile 

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0752 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.