C/C++的编码转换

本来以为转码只能用第三方库或者API的,没想到标准库也带了转码的函数

C语言

用到wcstombs、mbstowcs,编码要用setlocale设置,不过CRT增强版的_wcstombs_l和_mbstowcs_l可以设置局部的locale

#include <locale.h>
#include <stdlib.h>

char* W2A(wchar_t* src)
{
    _locale_t lc = _create_locale(LC_CTYPE, ""); // 使用系统设置的locale
    size_t size = 0;
    _wcstombs_s_l(&size, NULL, 0, src, _TRUNCATE, lc); // 获取缓冲size
    char* dst = (char*)malloc(size);
    _wcstombs_s_l(&size, dst, size, src, _TRUNCATE, lc);
    _free_locale(lc);
    return dst;
}

wchar_t* A2W(char* src)
{
    _locale_t lc = _create_locale(LC_CTYPE, ""); // 使用系统设置的locale
    size_t size = 0;
    _mbstowcs_s_l(&size, NULL, 0, src, _TRUNCATE, lc); // 获取缓冲size
    wchar_t* dst = (wchar_t*)malloc(size * sizeof(wchar_t));
    _mbstowcs_s_l(&size, dst, size, src, _TRUNCATE, lc);
    _free_locale(lc);
    return dst;
}

C++

用到C++11的wstring_convert的to_bytes和from_bytes,编码还是看locale

#include <locale>
#include <codecvt>

std::string W2A(const std::wstring& src)
{
    typedef std::codecvt<wchar_t, char, mbstate_t> cvttype;
    std::locale lc(""); // 使用系统设置的locale
    auto& cvt = std::use_facet<cvttype>(lc);
    std::wstring_convert<cvttype> cv(&cvt);
    return cv.to_bytes(src);
}

std::wstring A2W(const std::string& src)
{
    typedef std::codecvt<wchar_t, char, mbstate_t> cvttype;
    std::locale lc(""); // 使用系统设置的locale
    auto& cvt = std::use_facet<cvttype>(lc);
    std::wstring_convert<cvttype> cv(&cvt);
    return cv.from_bytes(src);
}

顺带一提如果要改变输出流的编码只需要调用imbue,还有codecvt头文件自带了各种Unicode编码转UTF-8的codecvt

#include <locale>
#include <codecvt>

// ...

    std::wofstream f(L"这是UTF-8文件.txt");
    f.imbue(std::locale(std::locale(), new std::codecvt_utf8_utf16<wchar_t>));
    f << L"这是UTF-16" << std::endl;

Windows API

这个知道的人就多了,用到WideCharToMultiByte和MultiByteToWideChar,可以设置代码页

#include <Windows.h>

char* W2A(wchar_t* src)
{
    int srcSize = (int)wcslen(src);
    int size = WideCharToMultiByte(CP_THREAD_ACP, 0, src, srcSize, NULL, 0, NULL, NULL);
    char* dst = (char*)malloc(size + 1);
    WideCharToMultiByte(CP_THREAD_ACP, 0, src, srcSize, dst, size + 1, NULL, NULL);
    dst[size] = '\0';
    return dst;
}

wchar_t* A2W(char* src)
{
    int srcSize = (int)strlen(src);
    int size = MultiByteToWideChar(CP_THREAD_ACP, 0, src, srcSize, NULL, 0);
    wchar_t* dst = (wchar_t*)malloc((size + 1) * sizeof(wchar_t));
    MultiByteToWideChar(CP_THREAD_ACP, 0, src, srcSize, dst, size + 1);
    dst[size] = L'\0';
    return dst;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章