utf8转ucs2编码c语言实现,C++字符转换

UTF_8与GBK

在windows平台下sizeof(wchar_t)为2,而在linux平台下sizeof(wchar_t)为4;

在windows平台下宽字符(或字符串)字面量使用UTF-16编码,linux平台下使用UTF-32编码。

MultiByteToWideChar、WideCharToMultiBytestd::string UTF8ToGBK(const std::string& strUTF8)

{

int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, NULL, 0);

WCHAR* wszGBK = new WCHAR[len + 1];

memset(wszGBK, 0, len * 2 + 2);

MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(LPCTSTR)strUTF8.c_str(), -1, wszGBK, len);

len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);

char *szGBK = new char[len + 1];

memset(szGBK, 0, len + 1);

WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);

std::string strTemp(szGBK);

delete[]szGBK;

delete[]wszGBK;

return strTemp;

}

std::string GBKToUTF8(const std::string& strGBK)

{

std::string strOutUTF8 = "";

WCHAR * str1;

int n = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0);

str1 = new WCHAR[n];

MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, str1, n);

n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);

char * str2 = new char[n];

WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL);

strOutUTF8 = str2;

delete[]str1;

str1 = NULL;

delete[]str2;

str2 = NULL;

return strOutUTF8;

}

MultiByteToWideChar、WideCharToMultiByte可以改变多字节与宽字节

CodePage参数控制字符集:

CodePage——指定要转换成的字符集代码页,它可以是任何已经安装的或系统自带的字符集,可选择以下代码页:

CP_ACP //当前系统ANSI代码页

CP_MACCP //当前系统Macintosh代码页

CP_OEMCP //当前系统OEM代码页,一种原始设备制造商硬件扫描码

CP_SYMBOL //Symbol代码页,用于Windows 2000及以后版本

CP_THREAD_ACP //当前线程ANSI代码页,用于Windows 2000及以后版本

CP_UTF7 //UTF-7,设置此值时lpDefaultChar和lpUsedDefaultChar都必须为NULL

CP_UTF8 //UTF-8,设置此值时lpDefaultChar和lpUsedDefaultChar都必须为NULL

用 GetLocaleInfo 函数获取当前系统的代码页,936: 简体中文, 950: 繁体中文,949:韩文

ATL封装_bstr_#include

#pragma comment(lib, "comsuppw.lib")

string ws2s(const wstring& ws)

{

_bstr_t t = ws.c_str();

char* pchar = (char*)t;

string result = pchar;

return result;

}

wstring s2ws(const string& s)

{

_bstr_t t = s.c_str();

wchar_t* pwchar = (wchar_t*)t;

wstring result = pwchar;

return result;

}

iconvint code_convert(char *from_charset, char *to_charset, char *inbuf, size_t inlen,

char *outbuf, size_t outlen) {

iconv_t cd;

char **pin = &inbuf;

char **pout = &outbuf;

cd = iconv_open(to_charset, from_charset);

if (cd == 0)

return -1;

memset(outbuf, 0, outlen);

if (iconv(cd, pin, &inlen, pout, &outlen) == -1)

return -1;

iconv_close(cd);

*pout = '\0';

return 0;

}

int u2g(char *inbuf, size_t inlen, char *outbuf, size_t outlen) {

return code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, outlen);

}

int g2u(char *inbuf, size_t inlen, char *outbuf, size_t outlen) {

return code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, outlen);

}

使用C++11标准库进行编码转换

下面是一段测试代码,print_code_uint_sequence函数模板用于输出字符串的码元序列。

#include

#include

#include

#include

template

void print_code_unit_sequence(tStringType str)

{

using char_type = typename tTraits::char_type;

static_assert(std::is_same::value || std::is_same::value || std::is_same::value, "error");

using unsigned_char_type = typename std::make_unsigned::type;

using unsigned_int_type = typename std::make_unsigned::type;

int w = std::is_same::value ? 2 : std::is_same::value ? 4 : 8;

for(auto c : str) {

auto value = static_cast(static_cast(c));

std::cout << "0x" << std::hex << std::uppercase << std::setw(w) << std::setfill('0') << value << ' ';

}

}

int main()

{

std::string u8_str = u8""; // utf-8

std::u16string u16_str = u""; // utf-16

std::u32string u32_str = U""; // ucs4

std::cout << "utf-8: ";

print_code_unit_sequence(u8_str);

std::cout << std::endl;

std::cout << "utf-16: ";

print_code_unit_sequence(u16_str);

std::cout << std::endl;

std::cout << "ucs4: ";

print_code_unit_sequence(u32_str);

std::cout << std::endl;

}

C++11标准库在头文件中定义了3个Unicode编码转换的Facet

std::codecvt_utf8 封装了UTF-8与UCS2及UTF-8与UCS4的编码转换

std::codecvt_utf16 封装了UTF-16与UCS2及UTF-16与UCS4的编码转换

std::codecvt_utf8_utf16 封装了UTF-8与UTF-16的编码转换

当要转换的字符串为std::basic_string使用

template

class Elem = wchar_t,

class Wide_alloc = std::allocator,

class Byte_alloc = std::allocator>

class wstring_convert;

UTF-8与UTF-16编码转换

UTF-8与UTF-16的编码转换使用std::codecvt_utf8_utf16类模板,其中Elem用于存储UTF-16码元,可以是char16_t、char32_t或wchar_t(这些类型都至少能够存储16bit)。

std::wstring_convert<:codecvt_utf8_utf16>, char16_t> cvt;

std::u16string u16_cvt_str = cvt.from_bytes(u8_source_str); // utf-8 to utf-16

std::string u8_cvt_str = cvt.to_bytes(u16_cvt_str); // utf-16 to utf-8

UTF-8与UCS2编码转换及UTF-8与UCS4编码转换

UTF-8与UCS2或UCS4编码转换使用std::codecvt_utf8类模板,当Elem为char16_t时转换为UTF-8与UCS2,当Elem为char32_t时转换为UTF-16与UCS4,当Elem为wchar_t时转换取决于实现。

std::wstring_convert<:codecvt_utf8>, char16_t> utf8_ucs2_cvt;

std::u16string ucs2_cvt_str = utf8_ucs2_cvt.from_bytes(u8_source_str); // utf-8 to ucs2

std::string u8_str_from_ucs2 = utf8_ucs2_cvt.to_bytes(ucs2_cvt_str); // ucs2 to utf-8

std::wstring_convert<:codecvt_utf8>, char32_t> utf8_ucs4_cvt;

std::u32string ucs4_cvt_str = utf8_ucs4_cvt.from_bytes(u8_source_str); // utf-8 to ucs4

std::string u8_str_from_ucs4 = utf8_ucs4_cvt.to_bytes(ucs4_cvt_str); // ucs4 to utf-8

UTF-16与UCS2编码转换及UTF-16与UCS4编码转换

UTF-16转UCS2或UCS4使用std::codecvt_utf16类模板

这里以UTF-16与UCS4的转换为例Elem为char32_t,UTF-16与UCS2的转换类似只是Elem需为char16_t。

由于std::wstring_convert是用于在byte string和wide string之间转换,使用std::codecvt_utf16时UTF-16字符串作为byte string,因此使用这个转换时就需要考虑字节序的问题。std::codecvt_utf16类模板的第3个模板参数Mode类型为std::codecvt_mode

enum codecvt_mode {

consume_header = 4,

generate_header = 2,

little_endian = 1

};consume_header 告诉codecvt需要处理输入的byte string中的BOM(Byte Order Mark)

generate_header 告诉codecvt在输出的byte string中添加BOM

little_endian 告诉codecvt将byte string的字节序视为小端(Little Endian),默认为大端(Big Endian)

std::wstring_convert<:codecvt_utf16 char32_t> utf16le_cvt; // little endian

std::wstring_convert<:codecvt_utf16 char32_t> utf16be_cvt; // default big endian

std::u32string u32_str_from_le = utf16le_cvt.from_bytes(u16le_byte_str); // utf-16 to ucs4

std::u32string u32_str_from_be = utf16be_cvt.from_bytes(u16be_byte_str); // utf-16 to ucs4

BOM(Byte Order Mark)

字节序标记是插入到以UTF-8、UTF-16或UTF-32编码Unicode文件开头的特殊标记,用于标识文本编码及字节序。

UTF-8 0xEF 0xBB 0xBF

UTF-16 BE 0xFE 0xFF

UTF-16 LE 0xFF 0xFE

UTF-32 BE 0x00 0x00 0xFE 0xFF

UTF-

你可能感兴趣的:(utf8转ucs2编码c语言实现,C++字符转换)