请教下字符编码的问题,UNICODE,UTF-8

时间:2023-01-05 13:15:54
先说说自己的理解
理解1:UNICODE是一个字符集,UTF-8,UTF-16等都是实现方式,通常所说的UTF-8转"UNICODE",这里的UNICODE其实是UTF-16(一个字符由2个字节表示),是这样吧。
理解2:多字节是相对单字节而言的,一个字符用2个或者2个以上的字节表示那就是多字节编码,是这样不。

现在有几个问题,CStringA中保存了UTF-8数据,如果强制转换成CStringW,是不是在CStringA中的每个字节在CStringW中都用2个字节来表示?
问题2:MultiByteToWideChar这个函数的第一个参数谁能用通俗点得文字给我扫盲下,MSDN上描述The code page to be used to perform the conversion. This parameter can be given the value of any code page that is installed or available in the system。。。。。。不理解,请赐教

17 个解决方案

#1


如果是UTF8转UTF16,不要用CStringA转CStringW,CStringA针对ANSI标准,ascii、gbk等编码可以转

请使用MultiByteToWideChar,有个参数可以选择输入是ANSI还是UTF8

#2


前几天有过类似问题,当CStringA强转CStringW时,CStringW的=()中会自动调用MultiByteToWideChar这个函数,并且使用当前的字符集(当前的字符集一般不可能是UTF-8,因此转换出错)

#3


引用 1 楼 jackyjkchen 的回复:
如果是UTF8转UTF16,不要用CStringA转CStringW,CStringA针对ANSI标准,ascii、gbk等编码可以转

请使用MultiByteToWideChar,有个参数可以选择输入是ANSI还是UTF8

能否说下第一个参数具体的含义,MSDN上的看不懂。。

#4


第一个参数不就下面那些么,我常用的也就CP_ACP和CP_UTF8。
ANSI 是微软默认编码。如果你写了
char *sz = "编码";用的就是ANSI,不是UTF-8。linux下,好像默认是utf-8

CP_ACP ANSI code page 
CP_MACCP Macintosh code page 
CP_OEMCP OEM code page 
CP_SYMBOL Windows 2000/XP: Symbol code page (42) 
CP_THREAD_ACP Windows 2000/XP: The current thread's ANSI code page 
CP_UTF7 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-7 
CP_UTF8 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-8. 

#5


UTF-8转UNICODE,转出来带有?,这个是什么情况,上点代码

int nLenW=MultiByteToWideChar(CP_UTF8, NULL, (CStringA)strBuf, -1, NULL, 0);
WCHAR *wszBuf=new WCHAR[nLenW+1];
char *chBody=new char[nLenW*2+1];
memset(chBody,0,nLenW*2+1);
memset(wszBuf,0,nLenW+1);

MultiByteToWideChar(CP_UTF8, NULL, (CStringA)strBuf, -1, wszBuf,nLenW);
WideCharToMultiByte(CP_ACP,NULL,wszBuf,-1,chBody,nLenW*2, NULL, FALSE);
strBody += chBody;
delete []wszBuf;
delete []chBody;

strBuf是一个CStringW类型的数据,服务器采用UTF-8,然后base64处理,客户端收到后先base64解码,把解码后的数据保存到CStringW类型的变量strBuf中。再把UTF-8转出来,但是转出来的带有?。。

#6


引用 5 楼 dahaii0 的回复:
UTF-8转UNICODE,转出来带有?,这个是什么情况,上点代码
C/C++ code

    int nLenW=MultiByteToWideChar(CP_UTF8, NULL, (CStringA)strBuf, -1, NULL, 0);
                    WCHAR *wszBuf=new WCHAR[nLenW+1];
                ……

再次强调,任何使用UTF8编码的都不要使用CString

#7


引用 6 楼 jackyjkchen 的回复:
引用 5 楼 dahaii0 的回复:

UTF-8转UNICODE,转出来带有?,这个是什么情况,上点代码
C/C++ code

int nLenW=MultiByteToWideChar(CP_UTF8, NULL, (CStringA)strBuf, -1, NULL, 0);
WCHAR *wszBuf=new WCHAR[nLenW+1];
……

再次强调,任何使用……

多谢,我先试下,

#8


这个真不知道,留名

#9


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
);

LPCSTR就是const char *,
int nLenW=MultiByteToWideChar(CP_UTF8, NULL,  (CStringA)strBuf, -1, NULL, 0);
你这转CStringA干嘛?
另外,如果你要用CString,那就用成员函数GetBuffer()来获得c风格的字符串,用完后记得ReleaseBuffer

#10


回楼上,因为strBuf是CStringW类型的,懒得转,所以直接强转。根据6楼大哥的指导改了下

                                        unsigned char *pDest = new unsigned char[1000];
memset(pDest,0,1000);
int nLength = 0;
CBase64 base64;
base64.DecodeBase64(strAnaly,pDest);


int nLenW=MultiByteToWideChar(CP_UTF8, NULL,(LPCSTR)pDest, -1, NULL, 0);
WCHAR *wszBuf=new WCHAR[nLenW+1];
char *chBody=new char[nLenW*2+1];
memset(chBody,0,nLenW*2+1);
memset(wszBuf,0,nLenW+1);

MultiByteToWideChar(CP_UTF8, NULL, (LPCSTR)pDest, -1, wszBuf,nLenW);
WideCharToMultiByte(CP_ACP,NULL,wszBuf,-1,chBody,nLenW*2, NULL, FALSE);
strBody += chBody;
delete []wszBuf;
delete []chBody;

#11


多谢9楼的回答,UNICODE下CString调用GetBuffer应该是得到wchar*把,NND,2005版的MSDN搜GetBuffer还要追到CSimpleStringT这里去。

#12


推荐使用WinHex软件查看文件原始字节内容。

#13


UNICODE是规定
UTF-8是编码方法

#14


MultiByteToWideChar
用这个函数吧

其实宽字节有一部分是为了汉字设计的,所以有时候要求你要将一个字节的转换为两个字节的,填充0就行了。

#15


MultiByteToWideChar(CP_UTF8..)   UTF-8转widechar
MultiByteToWideChar(CP_ACP..)    ascii转widechar
WideCharToMultiByte(CP_ACP)      widechar转ascii
WideCharToMultiByte(CP_UTF8)     这个。。应该没有这个吧?

#16


引用 15 楼 dahaii0 的回复:
MultiByteToWideChar(CP_UTF8..)   UTF-8转widechar
MultiByteToWideChar(CP_ACP..)    ascii转widechar
WideCharToMultiByte(CP_ACP)      widechar转ascii
WideCharToMultiByte(CP_UTF8)     这个。。应该没有这个吧?

如果你想ANSI和UTF-8互转,需要unicode做中转,ANSI先转UNICODE,然后UNICODE再转UTF-8

#17


非常感谢,C++版的就是热心啊。

#1


如果是UTF8转UTF16,不要用CStringA转CStringW,CStringA针对ANSI标准,ascii、gbk等编码可以转

请使用MultiByteToWideChar,有个参数可以选择输入是ANSI还是UTF8

#2


前几天有过类似问题,当CStringA强转CStringW时,CStringW的=()中会自动调用MultiByteToWideChar这个函数,并且使用当前的字符集(当前的字符集一般不可能是UTF-8,因此转换出错)

#3


引用 1 楼 jackyjkchen 的回复:
如果是UTF8转UTF16,不要用CStringA转CStringW,CStringA针对ANSI标准,ascii、gbk等编码可以转

请使用MultiByteToWideChar,有个参数可以选择输入是ANSI还是UTF8

能否说下第一个参数具体的含义,MSDN上的看不懂。。

#4


第一个参数不就下面那些么,我常用的也就CP_ACP和CP_UTF8。
ANSI 是微软默认编码。如果你写了
char *sz = "编码";用的就是ANSI,不是UTF-8。linux下,好像默认是utf-8

CP_ACP ANSI code page 
CP_MACCP Macintosh code page 
CP_OEMCP OEM code page 
CP_SYMBOL Windows 2000/XP: Symbol code page (42) 
CP_THREAD_ACP Windows 2000/XP: The current thread's ANSI code page 
CP_UTF7 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-7 
CP_UTF8 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-8. 

#5


UTF-8转UNICODE,转出来带有?,这个是什么情况,上点代码

int nLenW=MultiByteToWideChar(CP_UTF8, NULL, (CStringA)strBuf, -1, NULL, 0);
WCHAR *wszBuf=new WCHAR[nLenW+1];
char *chBody=new char[nLenW*2+1];
memset(chBody,0,nLenW*2+1);
memset(wszBuf,0,nLenW+1);

MultiByteToWideChar(CP_UTF8, NULL, (CStringA)strBuf, -1, wszBuf,nLenW);
WideCharToMultiByte(CP_ACP,NULL,wszBuf,-1,chBody,nLenW*2, NULL, FALSE);
strBody += chBody;
delete []wszBuf;
delete []chBody;

strBuf是一个CStringW类型的数据,服务器采用UTF-8,然后base64处理,客户端收到后先base64解码,把解码后的数据保存到CStringW类型的变量strBuf中。再把UTF-8转出来,但是转出来的带有?。。

#6


引用 5 楼 dahaii0 的回复:
UTF-8转UNICODE,转出来带有?,这个是什么情况,上点代码
C/C++ code

    int nLenW=MultiByteToWideChar(CP_UTF8, NULL, (CStringA)strBuf, -1, NULL, 0);
                    WCHAR *wszBuf=new WCHAR[nLenW+1];
                ……

再次强调,任何使用UTF8编码的都不要使用CString

#7


引用 6 楼 jackyjkchen 的回复:
引用 5 楼 dahaii0 的回复:

UTF-8转UNICODE,转出来带有?,这个是什么情况,上点代码
C/C++ code

int nLenW=MultiByteToWideChar(CP_UTF8, NULL, (CStringA)strBuf, -1, NULL, 0);
WCHAR *wszBuf=new WCHAR[nLenW+1];
……

再次强调,任何使用……

多谢,我先试下,

#8


这个真不知道,留名

#9


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
);

LPCSTR就是const char *,
int nLenW=MultiByteToWideChar(CP_UTF8, NULL,  (CStringA)strBuf, -1, NULL, 0);
你这转CStringA干嘛?
另外,如果你要用CString,那就用成员函数GetBuffer()来获得c风格的字符串,用完后记得ReleaseBuffer

#10


回楼上,因为strBuf是CStringW类型的,懒得转,所以直接强转。根据6楼大哥的指导改了下

                                        unsigned char *pDest = new unsigned char[1000];
memset(pDest,0,1000);
int nLength = 0;
CBase64 base64;
base64.DecodeBase64(strAnaly,pDest);


int nLenW=MultiByteToWideChar(CP_UTF8, NULL,(LPCSTR)pDest, -1, NULL, 0);
WCHAR *wszBuf=new WCHAR[nLenW+1];
char *chBody=new char[nLenW*2+1];
memset(chBody,0,nLenW*2+1);
memset(wszBuf,0,nLenW+1);

MultiByteToWideChar(CP_UTF8, NULL, (LPCSTR)pDest, -1, wszBuf,nLenW);
WideCharToMultiByte(CP_ACP,NULL,wszBuf,-1,chBody,nLenW*2, NULL, FALSE);
strBody += chBody;
delete []wszBuf;
delete []chBody;

#11


多谢9楼的回答,UNICODE下CString调用GetBuffer应该是得到wchar*把,NND,2005版的MSDN搜GetBuffer还要追到CSimpleStringT这里去。

#12


推荐使用WinHex软件查看文件原始字节内容。

#13


UNICODE是规定
UTF-8是编码方法

#14


MultiByteToWideChar
用这个函数吧

其实宽字节有一部分是为了汉字设计的,所以有时候要求你要将一个字节的转换为两个字节的,填充0就行了。

#15


MultiByteToWideChar(CP_UTF8..)   UTF-8转widechar
MultiByteToWideChar(CP_ACP..)    ascii转widechar
WideCharToMultiByte(CP_ACP)      widechar转ascii
WideCharToMultiByte(CP_UTF8)     这个。。应该没有这个吧?

#16


引用 15 楼 dahaii0 的回复:
MultiByteToWideChar(CP_UTF8..)   UTF-8转widechar
MultiByteToWideChar(CP_ACP..)    ascii转widechar
WideCharToMultiByte(CP_ACP)      widechar转ascii
WideCharToMultiByte(CP_UTF8)     这个。。应该没有这个吧?

如果你想ANSI和UTF-8互转,需要unicode做中转,ANSI先转UNICODE,然后UNICODE再转UTF-8

#17


非常感谢,C++版的就是热心啊。