IOS与Windows下字符集问题
由于之前手头上的事情比较多,一直没时间去理清思路去好好静下来去学习.关于之前完成的服务器端与客户端通信编码机的问题,一直都存在只是由于初期没打算做管理工具,相对于文字消息的发送的方面,服务器的工作也就只是一个转发而已.所以也就没去多考虑这个问题.直到后来需要向数据库,或者客户端主动发送写入的文字的时候,这个问题才不得不去花时间去解决.
大致介绍情况如下
1)ios与windows直接socket通信(使用boost单线程异步)
2)windows下通过mysql-connector对utf-8的数据库表进行操作
问题也是显而易见的,本身vs中未设置代码文件字符集,而选择的是多字符集.然后在ios(mysql)中相对应的字符集又与vs中使用的字符集不匹配,导致发送消息到ios上时,导致的中文乱码和在往mysql中插入中文时异常(incorrect string value异常),根据错误Incorrect string value: '\xF0\xA1\xA4\xA1\xEF\xBF...' for column 和 在ios上显示的乱码发现,问题的导致是由于不同字符编码集问题而导致的.
先简单看一下两端的编码
书面解释:
UTF-8:Unicode TransformationFormat-8bit,允许含BOM,但通常不含BOM。是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为(三个字节)来编码。UTF-8包含全世界所有国家需要用到的字符,是国际编码,通用性强。UTF-8编码的文字可以在各国支持UTF8字符集的浏览器上显示。如,如果是UTF8编码,则在外国人的英文IE上也能显示中文,他们无需下载IE的中文语言支持包。
GBK是国家标准GB2312基础上扩容后兼容GB2312的标准。GBK的文字编码是用双字节来表示的,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1。GBK包含全部中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBD大。
我的理解:
UTF-8使用3个字节来编码,而GBK(GB2312)使用2个字节来编码.同样的内容,显示的宽度改变,使相同中文字的不同的编码识别不出来.
解决办法:
1.对于mysql中可以通过在执行sql语句前进行执行"set names gbk"来告知db下面的语句使用gbk来编码,这样也就可以解决往数据库中插入中文的问题,但这样使用有一个副作用(可能是我的代码问题),这样执行后的结果可以很好的显示在数据库中,当取出后向IOS客户端发送时,在IOS上显示仍为乱码(直接在mysql中写入的不会出现这个问题).
2.对vs中本身要写入(或是操作的字符串string进行转码--最后会附上转码的代码),而关于这种转码在网上有比较多的资源,根据不同的操作系统环境也有不同的办法,由于服务器程序是部署在windows下的,我也就是使用了在windows下转换方法,而在linux下有iconv.h来解决问题(http://blog.csdn.net/jnbbwyth/article/details/6991371)
结论:
在windows下vs默认应该使用的是gbk(gb2132)编码,而在ios(mac)下xcode默认使用的utf-8.所以在相互通信或者操作的时候,注意转码.
暂时也就记录在这里了,很长一段时间没有更新了,自己太懒了.希望能慢慢的补上笔记了
附
CChineseCode.h
1 #pragma once 2 #include "comutil.h" 3 #pragma comment( lib, "comsuppw.lib" ) 4 #include <iostream> 5 using namespace std; 6 class CChineseCode 7 { 8 public: 9 CChineseCode(void); 10 ~CChineseCode(void); 11 static void UTF_8ToUnicode(wchar_t* pOut,char *pText); // 把UTF-8转换成Unicode 12 static void UnicodeToUTF_8(char* pOut,wchar_t* pText); //Unicode 转换成UTF-8 13 static void UnicodeToGB2312(char* pOut,wchar_t uData); // 把Unicode 转换成 GB2312 14 static void Gb2312ToUnicode(wchar_t* pOut,char *gbBuffer);// GB2312 转换成 Unicode 15 static void GB2312ToUTF_8(string& pOut,char *pText, int pLen);//GB2312 转为 UTF-8 16 static void UTF_8ToGB2312(string &pOut, char *pText, int pLen);//UTF-8 转为 GB2312 17 18 };
CChineseCode.cpp
1 #include "CChineseCode.h" 2 3 4 CChineseCode::CChineseCode(void) 5 { 6 } 7 8 9 CChineseCode::~CChineseCode(void) 10 { 11 } 12 void CChineseCode::UTF_8ToUnicode(wchar_t* pOut,char *pText) 13 { 14 char* uchar = (char *)pOut; 15 16 uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F); 17 uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F); 18 19 return; 20 } 21 22 void CChineseCode::UnicodeToUTF_8(char* pOut,wchar_t* pText) 23 { 24 // 注意 WCHAR高低字的顺序,低字节在前,高字节在后 25 char* pchar = (char *)pText; 26 27 pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4)); 28 pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6); 29 pOut[2] = (0x80 | (pchar[0] & 0x3F)); 30 31 return; 32 } 33 34 void CChineseCode::UnicodeToGB2312(char* pOut,wchar_t uData) 35 { 36 WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(wchar_t),NULL,NULL); 37 return; 38 } 39 40 void CChineseCode::Gb2312ToUnicode(wchar_t* pOut,char *gbBuffer) 41 { 42 ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1); 43 return ; 44 } 45 46 void CChineseCode::GB2312ToUTF_8(string& pOut,char *pText, int pLen) 47 { 48 char buf[4]; 49 int nLength = pLen* 3; 50 char* rst = new char[nLength]; 51 52 memset(buf,0,4); 53 memset(rst,0,nLength); 54 55 int i = 0; 56 int j = 0; 57 while(i < pLen) 58 { 59 //如果是英文直接复制就可以 60 if( *(pText + i) >= 0) 61 { 62 rst[j++] = pText[i++]; 63 } 64 else 65 { 66 wchar_t pbuffer; 67 Gb2312ToUnicode(&pbuffer,pText+i); 68 69 UnicodeToUTF_8(buf,&pbuffer); 70 71 unsigned short int tmp = 0; 72 tmp = rst[j] = buf[0]; 73 tmp = rst[j+1] = buf[1]; 74 tmp = rst[j+2] = buf[2]; 75 76 j += 3; 77 i += 2; 78 } 79 } 80 rst[j] = '\0'; 81 82 //返回结果 83 pOut = rst; 84 delete []rst; 85 86 return; 87 } 88 89 void CChineseCode::UTF_8ToGB2312(string &pOut, char *pText, int pLen) 90 { 91 char * newBuf = new char[pLen]; 92 char Ctemp[4]; 93 memset(Ctemp,0,4); 94 95 int i =0; 96 int j = 0; 97 98 while(i < pLen) 99 { 100 if(pText[i] > 0) 101 { 102 newBuf[j++] = pText[i++]; 103 } 104 else 105 { 106 WCHAR Wtemp; 107 UTF_8ToUnicode(&Wtemp,pText + i); 108 109 UnicodeToGB2312(Ctemp,Wtemp); 110 111 newBuf[j] = Ctemp[0]; 112 newBuf[j + 1] = Ctemp[1]; 113 114 i += 3; 115 j += 2; 116 } 117 } 118 newBuf[j] = '\0'; 119 120 pOut = newBuf; 121 delete []newBuf; 122 123 return; 124 }