Windows编程下的字符串格式及编码问题

Posted CodeBowl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Windows编程下的字符串格式及编码问题相关的知识,希望对你有一定的参考价值。

大家在学习或者使用Windows编程中,经常会碰到字符串之间的转换,char*转LPCWSTR也是其中一个比较常见的转换。下面就列出几种比较常用的转换方法。大家可以根据自己的需求选择相对应的方法,下面来一起学习学习吧。

为什么总结这个问题

一些代码在其他平台下是正常的,但是在Windows环境下,经常遇到中文乱码的情况,很是头疼!

1、通过MultiByteToWideChar函数转换

MultiByteToWideChar函数是将多字节转换为宽字节的一个API函数,它的原型如下:

int MultiByteToWideChar( 
 UINT CodePage,   // code page 
 DWORD dwFlags,   // character-type options 
 LPCSTR lpMultiByteStr, // string to map 
 int cbMultiByte,  // number of bytes in string 
 LPWSTR lpWideCharStr, // wide-character buffer 
 int cchWideChar  // size of buffer 
);

LPCWSTR实际上也是CONST WCHAR *类型

 char* szStr = "测试字符串"; 
WCHAR wszClassName[256]; 
memset(wszClassName,0,sizeof(wszClassName)); 
MultiByteToWideChar(CP_ACP,0,szStr,strlen(szStr)+1,wszClassName, 
 sizeof(wszClassName)/sizeof(wszClassName[0]));

2、通过T2W转换宏

  char* szStr = "测试字符串";  
CString str = CString(szStr); 
USES_CONVERSION; 
LPCWSTR wszClassName = new WCHAR[str.GetLength()+1]; 
wcscpy((LPTSTR)wszClassName,T2W((LPTSTR)str.GetBuffer(NULL))); 
str.ReleaseBuffer();

3、通过A2CW转换

char* szStr = "测试字符串";  
CString str = CString(szStr); 
USES_CONVERSION; 
LPCWSTR wszClassName = A2CW(W2A(str)); 
str.ReleaseBuffer();

上述方法都是UniCode环境下测试的。

4.编码格式转换:ANSI,UTF-8,UNICODE字符在Windows下的转换

//convert_code.hpp
//调用后不要忘记delete[]掉

#pragma once
#include <windows.h>

static const wchar_t* ConvertUtf8ToUnicode(const char* _ansiUtf8)
{
	if (_ansiUtf8 == NULL)
	{
		return L"";
	}
	int len = MultiByteToWideChar(CP_UTF8, 0, _ansiUtf8, -1, NULL, 0);
	wchar_t* wszUnicode = new wchar_t[(size_t)len + 1];
	memset(wszUnicode, 0, ((size_t)len + 1) * sizeof(wchar_t));
	MultiByteToWideChar(CP_UTF8, 0, _ansiUtf8, -1, wszUnicode, len);
	return wszUnicode;
}


static const char* ConvertUnicodeToUtf8(const wchar_t* _szUnicode)
{
	if (_szUnicode == NULL)
	{
		return "";
	}
	int len = WideCharToMultiByte(CP_UTF8, 0, _szUnicode, -1, NULL, 0, NULL, NULL);
	char* szUtf8 = new char[(size_t)len + 1];
	memset(szUtf8, 0, ((size_t)len + 1) * sizeof(char));
	WideCharToMultiByte(CP_UTF8, 0, _szUnicode, -1, szUtf8, len, NULL, NULL);
	return szUtf8;
}


static const wchar_t* ConvertAnsiToUnicode(const char* _szAnsi)
{
	if (_szAnsi == NULL)
	{
		return L"";
	}
	int len = MultiByteToWideChar(CP_ACP, 0, _szAnsi, -1, NULL, 0);
	wchar_t* wszUnicode = new wchar_t[(size_t)len + 1];
	memset(wszUnicode, 0, ((size_t)len + 1) * sizeof(wchar_t));
	MultiByteToWideChar(CP_ACP, 0, _szAnsi, -1, wszUnicode, len);
	return wszUnicode;
}


static const char* ConvertUnicodeToAnsi(const wchar_t* _szUnicode)
{
	if (_szUnicode == NULL)
	{
		return "";
	}
	int len = WideCharToMultiByte(CP_ACP, 0, _szUnicode, -1, NULL, 0, NULL, NULL);
	char* szAnsi = new char[(size_t)len + 1];
	memset(szAnsi, 0, ((size_t)len + 1) * sizeof(char));
	WideCharToMultiByte(CP_ACP, 0, _szUnicode, -1, szAnsi, len, NULL, NULL);
	return szAnsi;
}


static const char* ConvertAnsiToUtf8(const char* _szAnsi)
{
	if (NULL == _szAnsi)
	{
		return "";
	}
	int dwAnsiLen = MultiByteToWideChar(CP_ACP, NULL, _szAnsi, -1, NULL, NULL);
	wchar_t* szTmpUnicode = new wchar_t[(size_t)dwAnsiLen + 1];
	memset(szTmpUnicode, 0, sizeof(wchar_t) * ((size_t)dwAnsiLen + 1));
	MultiByteToWideChar(CP_ACP, NULL, _szAnsi, -1, szTmpUnicode, dwAnsiLen);

	int dwUtf8Len = WideCharToMultiByte(CP_UTF8, 0, szTmpUnicode, -1, NULL, 0, NULL, NULL);
	char* szUtf8 = new char[(size_t)dwUtf8Len + 1];
	memset(szUtf8, 0, sizeof(char) * ((size_t)dwUtf8Len + 1));
	WideCharToMultiByte(CP_UTF8, 0, szTmpUnicode, -1, szUtf8, dwUtf8Len, NULL, NULL);
	delete[] szTmpUnicode;

	return szUtf8;
}


static const char* ConvertUtf8ToAnsi(const char* _szUtf8)
{
	if (NULL == _szUtf8)
	{
		return "";
	}
	int dwAnsiLen = MultiByteToWideChar(CP_UTF8, NULL, _szUtf8, -1, NULL, NULL);
	wchar_t* szTmpUnicode = new wchar_t[(size_t)dwAnsiLen + 1];
	memset(szTmpUnicode, 0, sizeof(wchar_t) * ((size_t)dwAnsiLen + 1));
	MultiByteToWideChar(CP_UTF8, NULL, _szUtf8, -1, szTmpUnicode, dwAnsiLen);

	int dwUtf8Len = WideCharToMultiByte(CP_ACP, 0, szTmpUnicode, -1, NULL, 0, NULL, NULL);
	char* szAnsi = new char[(size_t)dwUtf8Len + 1];
	memset(szAnsi, 0, sizeof(char) * ((size_t)dwUtf8Len + 1));
	WideCharToMultiByte(CP_ACP, 0, szTmpUnicode, -1, szAnsi, dwUtf8Len, NULL, NULL);
	delete[] szTmpUnicode;

	return szAnsi;
}

5. utf-8和GBK转换

除了一些旧的、没有考虑到兼容性的网页还在用gbk做编码外,大部分的网页都已经用utf-8做编码了。但是最令人头疼的是,windows的控制台是很不好显示utf-8的。

#include <string>
#include <windows.h>
using std::string;

//gbk 转 utf8
string GBKToUTF8(const string& strGBK)
{
    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;
}

//utf-8 转 gbk
string UTF8ToGBK(const string& strUTF8)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, NULL, 0);
    unsigned short * wszGBK = new unsigned short[len + 1];
    memset(wszGBK, 0, len * 2 + 2);
    MultiByteToWideChar(CP_UTF8, 0, (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);
    //strUTF8 = szGBK;
    std::string strTemp(szGBK);
    delete[]szGBK;
    delete[]wszGBK;
    return strTemp;
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

参考资料

http://www.cppblog.com/Shihira/archive/2013/10/28/200124.aspx

以上是关于Windows编程下的字符串格式及编码问题的主要内容,如果未能解决你的问题,请参考以下文章

Windows下的字符编码转换

Linux 如何查看文件编码格式及转换文件编码

linux文件编码转换及Windows上创建的文件转为Linux格式

文件编码格式转换

Linux解决乱码问题以及查看文件编码方式

Windows下的文件名是啥编码的