UTF-8与ANSI 编码转换

http://blog.csdn.net/bitsjx/article/details/5664931

平时Coding的时候,经常会遇到一些编码转换的问题,尤其是UTF-8与ANSI 编码转换的问题。遇到好多回了,所以不得不拿出来单独看一下。其实这个问题如果知道怎么做的话也不是问题,但是第一次接触到的时候我却是费了好大的功夫才搞出来!

看一下下面的代码


//utf编码转换为ansi编码 
string CDownLoadFile::Utf82Ansi(const char* srcCode)
{	
	int srcCodeLen=0;
	srcCodeLen=MultiByteToWideChar(CP_UTF8,NULL,srcCode,strlen(srcCode),NULL,0);
	wchar_t* result_t=new wchar_t[srcCodeLen+1];
	MultiByteToWideChar(CP_UTF8,NULL,srcCode,strlen(srcCode),result_t,srcCodeLen);
	result_t[srcCodeLen]='/0';
	srcCodeLen=WideCharToMultiByte(CP_ACP,NULL,result_t,wcslen(result_t),NULL,0,NULL,NULL);
	char* result=new char[srcCodeLen+1];
	WideCharToMultiByte(CP_ACP,NULL,result_t,wcslen(result_t),result,srcCodeLen,NULL,NULL);
	result[srcCodeLen]='/0';
	string srcAnsiCode="";
	srcAnsiCode=(string)result;
	delete result_t;
	delete result;
	return srcAnsiCode;
}

其中两个主要的函数为:

int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar);

函数功能:该函数映射一个字符串到一个宽字符(unicode)的字符串。由该函数映射的字符串没必要是多字节字符组。

int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPWSTR lpWideCharStr, int cchWideChar, LPCSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, PBOOL pfUsedDefaultChar );

函数功能:该函数映射一个unicode字符串到一个多字节字符串。

具体参数百度百科讲的很明白,看一下就知道怎么回事了,我就不赘述了。

其实就是这么点问题,但是自己解决的时候却费了很大的力气,好处就是如果别的事情我可以我可以忘掉,但是这个我真的再也忘不掉了!


问题:

sqlite 的编码格式为ANSI

Qt 默认的编码格式为UTF-8

http://bbs.csdn.net/topics/360212350


解决方法:

Sqlite默认保存数据是用UTF8格式,而现有程序开发工具都是默认GB2312的格式,所以你编程写的中文不转码直接写到库里后,用任何数据库工具看肯定都是乱码。但是读出来之后仍然是GB2312,所以显示正常。反之如果你用数据库工具写中文,则默认存UTF8格式,用程序读出来就是乱码。也就是你说的不可兼得。
   如果要实现能够编程和数据库工具读写都正常,必须要转码。也就是说,保存时候,要把GB2312转成UTF8,而读出时候需要把UTF8在转成GB2312。
   网上有源程序可用,叫做CCodingConv的类,你搜一个源码,在每次执行SQL语句之前,将其转换一下即可。将整个SQL语句进行转换,E文的会保持不变,而中文的会自动转换成合适的编码,执行即可实现要求。

有关unicode,UTF-8及 ANSI等编码转换

1. ANSI 
美国国家标准码,操作系统默认的编码格式;但是不同国家有不同的文字,由此各个国家制定了自己的国标码,如GB2312等。注意,各个国家制定时还是按照ANSI准则进行的:即不属于ASCII(0~127)的一个文字(符号)占两个字节,属于ASCII的占一个字节。这样一来,一个大字符串用不同国标码,解释的结果就不同(但一点就是,属于ASCII部分的字符解释出来是相同的)。 

ANSI是编码,GB2312等国标码是符合ANSI标准的字符集。字符集与编码是两回事。 

2. 字符 
字符是一个符号,如:'#','◎'等,存储时根据不同的编码标准可能占用1个或多个字节的空间。不同编码标准下,字符占用空间大小不同,如Unicode编码所有字符都是2个字节,utf-8编码占用从1个到6个不等。 

3. 多字节字符串: 
字符串在内存中,如果“字符”是以ANSI编码形式存放的,则一个字符可能使用一个字节或多个字节来表示,称这个字符串为ANSI字符串或多字节字符串。 

4. Unicode: 
统一码,任何字符都占两个字节。各个国家文字、符号统一编码。 

VC++或其他编程工具对汉字或字符都采用操作系统的编码标准,一般都是ANSI标准。这就涉及往其它编码转化的问题。 

5. ANSI与Unicode 
如果ANSI全部属于ASCII(0~127),则 mbstowcs, wcstombs 即可。因为Unicode对ASCII(0~127)的处理是“直接扩展ANSI”--由一个字节到两个字节。 

size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count ); 
size_t wcstombs( char *mbstr, const wchar_t *wcstr, size_t count );对于不属于ASCII的,如汉字,使用 WideCharToMultiByte,MultiByteToWideChar。 

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 
); 
6. 多字节到宽字符(Unicode) 
待转换的字符并不一定是多字节字符串(ANSI字符串),uft-8编码的也可以。 

CodePage:待转换的代码页,如CP_ACP(ANSI),utf-8; 
dwFlags: 0; 
lpMultiByteStr,cbMultiByte:待转换 
lpWideCharStr,cchWideChar:转换完 

int WideCharToMultiByte( 
UINT CodePage, // code page 
DWORD dwFlags, // performance and mapping flags 
LPCWSTR lpWideCharStr, // wide-character string 
int cchWideChar, // number of chars in string 
LPSTR lpMultiByteStr, // buffer for new string 
int cbMultiByte, // size of buffer 
LPCSTR lpDefaultChar, // default for unmappable chars 
LPBOOL lpUsedDefaultChar // set when default char used 
); 
7. 宽字符(Unicode)到多字节 
新字符串不必是多字节(ANSI)字符集。 

CodePag:要转换成的代码页,如CP_ACP(ANSI),utf-8; 
dwFlags:0; 
lpWideCharStr,cchWideChar:待转换 
lpMultiByteStr,cbMultiByte:转换完 
lpDefaultChar,lpUsedDefaultChar:失败时缺省字符; 

一个字符串中有utf-8,如何转换成ANSI? 
首先,utf-8 到 Unicode 
其次,Unicode 到 ANSI 

代码如下: 

int ConvUtf8ToAnsi(CString& strSource, CString& strChAnsi) 

if (strSource.GetLength() <= 0) 
return 0; 

CString strWChUnicode; 

strSource.TrimLeft(); 
strSource.TrimRight(); 
strChAnsi.Empty(); 

int iLenByWChNeed = MultiByteToWideChar(CP_UTF8, 0, 
strSource.GetBuffer(0), 
strSource.GetLength(), 
NULL, 0); 

int iLenByWchDone = MultiByteToWideChar(CP_UTF8, 0, 
strSource.GetBuffer(0), 
strSource.GetLength(), 
(LPWSTR)strWChUnicode.GetBuffer(iLenByWChNeed * 2), 
iLenByWChNeed); 

strWChUnicode.ReleaseBuffer(iLenByWchDone * 2); 

int iLenByChNeed = WideCharToMultiByte(CP_ACP, 0, 
(LPCWSTR)strWChUnicode.GetBuffer(0), 
iLenByWchDone, 
NULL, 0, 
NULL, NULL); 

int iLenByChDone = WideCharToMultiByte(CP_ACP, 0, 
(LPCWSTR)strWChUnicode.GetBuffer(0), 
iLenByWchDone, 
strChAnsi.GetBuffer(iLenByChNeed), 
iLenByChNeed, 
NULL, NULL); 

strChAnsi.ReleaseBuffer(iLenByChDone); 

if (iLenByWChNeed != iLenByWchDone || iLenByChNeed != iLenByChDone) 
return 1; 

return 0; 

8. Unicode 到 ANSI 其它方法 
1. 调用CRT 函数wcstombs(); 
2. 使用CString 构造器或赋值操作(仅用于MFC ); 
3. 使用ATL 串转换宏; 

size_t wcstombs ( 
char* mbstr, // 接受结果ANSI串的字符(char)缓冲。 
const wchar_t* wcstr, // 要转换的Unicode串。 
size_t count ); // mbstr参数所指的缓冲大小。 
MFC中的CString包含有构造函数和接受Unicode串的赋值操作,所以你可以用CString来实现转换。 

// 假设有一个Unicode串wszSomeString... 
CString str1 ( wszSomeString ); // 用构造器转换 
CString str2; 
str2 = wszSomeString; // 用赋值操作转换 

ATL有一组很方便的宏用于串的转换。W2A()用于将Unicode串转换为ANSI串(记忆方法是“wide to ANSI”——宽字符到ANSI)。实际上使用OLE2A()更精确,“OLE”表示的意思是COM串或者OLE串。 

9. VC6 IDE下查看Unicode字符的方法 
unicode字符后面加",su"


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值