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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章