본문 바로가기

서버 관리/리눅스

multibyte string to widechar string

[1. 개요]

멀티바이트 형태의 문자열(UTF-8) 을 wide char 형태의 문자열(유니코드) 로 변환하는 방법 정리.


[2. 오해]

std::string 을 std::wstring 으로 변환하는 방법을 단순히 아래와 같은 방법으로 알고 있었는데, 

아래 방법은 틀린 방법이다.

  • std::wstring wstr(str.begin(), str.end());

위 코드는 단순히 멀티바이트 형태의 string 의 내부 버퍼를 복사할 뿐이다.

#include <iostream>
#include <string>
#include <cstring>

int main()
{
        const char * buf = "안녕하세요";
        std::string str = buf;
        std::wstring wstr(str.begin(), str.end());

        std::cout << strlen(buf) << std::endl;
        std::cout << str.length() << std::endl;
        std::cout << wstr.length() << std::endl;

        std::cout << buf << std::endl;
        std::cout << str << std::endl;
        std::wcout << wstr << std::endl;

        return 0;
}

 

위 코드의 출력은 아래와 같다.

출력
15
15
15
안녕하세요
안녕하세요
안녕하세요

[3. 변환]

C++11 이상에서 사용할 수 있는 한가지 방법은 아래와 같다.

#include <iostream>
#include <string>
#include <cstring>
#include <locale>  // 항상 codecvt 헤더 보다 먼저 와야 한다.(?)
#include <codecvt>

int main()
{
        std::string sbuf = "안녕하세요";

        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
        std::wstring wideStr = converter.from_bytes(sbuf.data());

        std::cout << "multibyte length " <<  sbuf.length() << std::endl;
        std::cout << "output " << sbuf << '\n' << std::endl;

        std::wcout << L"widechar length is " << wideStr.length() << std::endl;
        std::wcout << L"result is " <<  wideStr << std::endl;
        for (const auto wc : wideStr) {
                std::cout << int(wc) << " ";
        }
        std::cout << std::endl;

        return 0;
}
출력
multibyte length 15
output 안녕하세요

widechar length is 5
result is HUX8▒
50504 45397 54616 49464 50836

 

wide char 문자열 출력은 인코딩 지원 여부에 따라 깨질 수 있다.

  • std::setlocale(LC_ALL, "en_US.UTF-8");  // 로케일 설정 (해야하나?)

하지만, 문자열의 길이는 정확히 5자로 출력되었다.


[4. 그외]

mbstowsc() 도 있긴 한데...