UTF8、多字节、Unicode字符串的常用转换(MFC)

接口

CStringA UTF8AndMB_Convert(const CStringA &strSource, UINT nSourceCodePage, UINT nTargetCodePage); // UTF8与多字节(MultiByte)互转
CStringA UTF8ToMB(const CStringA& utf8Str);
CStringA MBToUTF8(const CStringA& MBStr);
CStringA UnicodeToUTF8(const CStringW& unicodeStr);
CStringW UTF8ToUnicode(const CStringA& utf8Str);
bool IsTextUTF8(const char* str, ULONGLONG length);

实现

// UTF8与多字节(MultiByte)互转
CStringA UTF8AndMB_Convert(const CStringA &strSource, UINT nSourceCodePage, UINT nTargetCodePage)
{
	int nSourceLen = strSource.GetLength();
	int nWideBufLen = MultiByteToWideChar(nSourceCodePage, 0, strSource, -1, NULL, 0);

	wchar_t* pWideBuf = new wchar_t[nWideBufLen + 1];
	memset(pWideBuf, 0, (nWideBufLen + 1) * sizeof(wchar_t));

	MultiByteToWideChar(nSourceCodePage, 0, strSource, -1, (LPWSTR)pWideBuf, nWideBufLen);

	char* pMultiBuf = NULL;
	int nMiltiBufLen = WideCharToMultiByte(nTargetCodePage, 0, (LPWSTR)pWideBuf, -1, (char *)pMultiBuf, 0, NULL, NULL);

	pMultiBuf = new char[nMiltiBufLen + 1];
	memset(pMultiBuf, 0, nMiltiBufLen + 1);

	WideCharToMultiByte(nTargetCodePage, 0, (LPWSTR)pWideBuf, -1, (char *)pMultiBuf, nMiltiBufLen, NULL, NULL);

	CStringA strTarget(pMultiBuf);

	delete[] pWideBuf;
	delete[] pMultiBuf;

	return strTarget;
}

CStringA UTF8ToMB(const CStringA& utf8Str)
{
	if (IsTextUTF8(utf8Str, utf8Str.GetLength()))
	{
		return UTF8AndMB_Convert(utf8Str, CP_UTF8, CP_ACP);
	}

	return utf8Str;
}

CStringA MBToUTF8(const CStringA& MBStr)
{
	return UTF8AndMB_Convert(MBStr, CP_ACP, CP_UTF8);
}

CStringA UnicodeToUTF8(const CStringW& unicodeStr)
{
	char* pMultiBuf = NULL;
	int nMiltiBufLen = WideCharToMultiByte(CP_UTF8, 0, unicodeStr, -1, pMultiBuf, 0, NULL, NULL);

	pMultiBuf = new char[nMiltiBufLen + 1];
	memset(pMultiBuf, 0, nMiltiBufLen + 1);

	WideCharToMultiByte(CP_UTF8, 0, unicodeStr, -1, (char *)pMultiBuf, nMiltiBufLen, NULL, NULL);

	CStringA strTarget(pMultiBuf);
	delete[] pMultiBuf;

	return strTarget;
}

CStringW UTF8ToUnicode(const CStringA& utf8Str)
{
	UINT codepage = CP_UTF8;
	if (!IsTextUTF8(utf8Str, utf8Str.GetLength()))
	{
		codepage = CP_ACP;
	}

	int nSourceLen = utf8Str.GetLength();
	int nWideBufLen = MultiByteToWideChar(codepage, 0, utf8Str, -1, NULL, 0);

	wchar_t* pWideBuf = new wchar_t[nWideBufLen + 1];
	memset(pWideBuf, 0, (nWideBufLen + 1) * sizeof(wchar_t));

	MultiByteToWideChar(codepage, 0, utf8Str, -1, (LPWSTR)pWideBuf, nWideBufLen);

	CStringW strTarget(pWideBuf);
	delete[] pWideBuf;

	return strTarget;
}

bool IsTextUTF8(const char* str, ULONGLONG length)
{
	DWORD nBytes = 0;//UFT8可用1-6个字节编码,ASCII用一个字节
	UCHAR chr;
	bool bAllAscii = true; //如果全部都是ASCII, 说明不是UTF-8
	for (int i = 0; i < length; i++)
	{
		chr = *(str + i);
		if ((chr & 0x80) != 0) // 判断是否ASCII编码,如果不是,说明有可能是UTF-8,ASCII用7位编码,但用一个字节存,最高位标记为0,o0xxxxxxx
			bAllAscii = false;
		if (nBytes == 0) //如果不是ASCII码,应该是多字节符,计算字节数
		{
			if (chr >= 0x80)
			{
				if (chr >= 0xFC && chr <= 0xFD)
					nBytes = 6;
				else if (chr >= 0xF8)
					nBytes = 5;
				else if (chr >= 0xF0)
					nBytes = 4;
				else if (chr >= 0xE0)
					nBytes = 3;
				else if (chr >= 0xC0)
					nBytes = 2;
				else
				{
					return false;
				}
				nBytes--;
			}
		}
		else //多字节符的非首字节,应为 10xxxxxx
		{
			if ((chr & 0xC0) != 0x80)
			{
				return false;
			}
			nBytes--;
		}
	}

	if (nBytes > 0) //违返规则
	{
		return false;
	}

	if (bAllAscii) //如果全部都是ASCII, 说明不是UTF-8
	{
		return false;
	}

	return true;
}

测试代码

CStringW str("中文");
CStringA utf8Str = UnicodeToUTF8(str);

CStringW unicodeStr = UTF8ToUnicode(utf8Str);
CStringA mbStr = UTF8ToMB(utf8Str);

CStringW unicodeStr2 = UTF8ToUnicode(mbStr);
CStringA utr8Str2 = MBToUTF8(mbStr);
CStringW unicodeStr3 = UTF8ToUnicode(utr8Str2);

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注