`
xpp02
  • 浏览: 1053837 次
社区版块
存档分类
最新评论

一网打尽中文编码转换---6种编码30个方向的转换

 
阅读更多
一网打尽中文编码转换——6编码30个方向的转换

1.问题提出

在学编程序时,曾经有人问过“你可以编一个记事本程序吗?”当时很不屑一顾,但是随着学习MFC的深入,了解到记事本程序也并非易事,难点就是四种编码之间的转换。

对于编码,这是一个令初学者头疼的问题,特别是对于编码的转换,更是难以捉摸。笔者为了完成毕业设计中的一个编码转换模块,研究了中文编码和常见的字符集后,决定解决"记事本"程序的编码问题,更进一步完成GB2312、Big5、GBK、Unicode 、Unicode big endian、UTF-8共6种编码之间的任意转换。

2.问题解决

(1)编码基础知识

a.了解编码和字符集

这部分内容,我不在赘述,可参见CSDN Ancky的专栏中《各种字符集和编码详解》

博客地址:http://blog.csdn.net/ancky/article/details/2034809

b.单字节、双字节、多字节

这部分内容,可参见我先前翻译的博文《C++字符串完全指南--第一部分:win32字符编码》

博客地址:http://blog.csdn.net/ziyuanxiazai123/article/details/7482360

c.区域和代码页

这部分内容,可参见博客 http://hi.baidu.com/tzpwater/blog/item/bd4abb0b60bff1db3ac7636a.html

d.中文编码GB2312、GBK、Big5,这部分内容请参见CSDN lengshine 博客中《GB2312、GBK、Big5汉字编码
》,博客地址:http://blog.csdn.net/lengshine/article/details/5470545

e.Windows程序的字符编码

这部分内容,可参见博客http://blog.sina.com.cn/s/blog_4e3197f20100a6z2.html 中《Windows程序的字符编码》

(2)编码总结

a.六种编码的特点

六种编码的特点如下图所示:

b.编码存储差别

ANSI(在简体中文中默认为GB2312)、Unicode、Unicode big endian 、UTF-8存储存在差别。

以中文"你好"二字为例,他们存贮格式如下图所示:

c.GB2312、Big5、GBK编码的区别

三者中汉字均采用二个字节表示,但是字节表示的值范围有所不同,如下图所示:


(3)编码转换方式

6种编码互相转换,由排列组合知识知道共有30个方向的转换.笔者采用的转换方法,

多字节文件与Unicode文件转换如下图所示:

多字节文件之间转换如下图所示:

(4)编码转换使用的三个函数

a.MultiByteToWideChar

该函数完成多字节字符串向Unicode宽字符串的转换.

函数原型为:

int MultiByteToWideChar(
 UINT CodePage, // 代码页
 DWORD dwFlags, // 转换标志
 LPCSTR lpMultiByteStr, // 待转换的字符串
 int cbMultiByte, // 待转换字符串的字节数目
 LPWSTR lpWideCharStr, // 转换后宽字符串的存储空间
 int cchWideChar // 转换后宽字符串的存储空间大小 以宽字符大小为单位
);
b.WideCharToMultiByte
该函数完成Unicode宽字符串到多字节字符串的转换,使用方法具体参见MSDN。
以上两个函数可以完成大部分的字符串转换,可以将其封装成多字节和宽字节之间的转换函数:

  1. wchar_t*Coder::MByteToWChar(UINTCodePage,LPCSTRlpcszSrcStr)
  2. {
  3. LPWSTRlpcwsStrDes=NULL;
  4. intlen=MultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,NULL,0);
  5. lpcwsStrDes=newwchar_t[len+1];
  6. if(!lpcwsStrDes)
  7. returnNULL;
  8. memset(lpcwsStrDes,0,sizeof(wchar_t)*(len+1));
  9. len=MultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,lpcwsStrDes,len);
  10. if(len)
  11. returnlpcwsStrDes;
  12. else
  13. {
  14. delete[]lpcwsStrDes;
  15. returnNULL;
  16. }
  17. }
  18. char*Coder::WCharToMByte(UINTCodePage,LPCWSTRlpcwszSrcStr)
  19. {
  20. char*lpszDesStr=NULL;
  21. intlen=WideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,NULL,0,NULL,NULL);
  22. lpszDesStr=newchar[len+1];
  23. memset(lpszDesStr,0,sizeof(char)*(len+1));
  24. if(!lpszDesStr)
  25. returnNULL;
  26. len=WideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,lpszDesStr,len,NULL,NULL);
  27. if(len)
  28. returnlpszDesStr;
  29. else
  30. {
  31. delete[]lpszDesStr;
  32. returnNULL;
  33. }
  34. }
c.LCMapString 依赖于本地机器的字符转换函数,尤其是中文编码在转换时要依赖于本地机器, 直接利用上述a、b中叙述的函数会产生错误,例如直接从GB2312转换到Big5,利用
MultiByteToWideChar函数将GB2312转换到Unicode字符串,然后从Unicode字符串利用函数
WideCharToMultiByte转换成Big5,将会发生错误,错误的结果如下图所示:


因此中文编码转换时适当使用LCMapString函数,才能完成正确的转换.
例如:

  1. //简体中文GB2312转换成繁体中文BIG5
  2. char*Coder::GB2312ToBIG5(constchar*szGB2312Str)
  3. {
  4. LCIDlcid=MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);
  5. intnLength=LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,-1,NULL,0);
  6. char*pBuffer=newchar[nLength+1];
  7. if(!pBuffer)
  8. returnNULL;
  9. LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,-1,pBuffer,nLength);
  10. pBuffer[nLength]=0;
  11. wchar_t*pUnicodeBuff=MByteToWChar(CP_GB2312,pBuffer);
  12. char*pBIG5Buff=WCharToMByte(CP_BIG5,pUnicodeBuff);
  13. delete[]pBuffer;
  14. delete[]pUnicodeBuff;
  15. returnpBIG5Buff;
  16. }
(5)编码实现 实现Coder类完成编码转换工作. Coder类的代码清单如下:
  1. //Coder.h:interfacefortheCoderclass.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #if!defined(AFX_ENCODING_H__2AC955FB_9F8F_4871_9B77_C6C65730507F__INCLUDED_)
  5. #defineAFX_ENCODING_H__2AC955FB_9F8F_4871_9B77_C6C65730507F__INCLUDED_
  6. #if_MSC_VER>1000
  7. #pragmaonce
  8. #endif//_MSC_VER>1000
  9. //-----------------------------------------------------------------------------------------------
  10. //程序用途:实现GB2312、big5、GBK、Unicode、Unicodebigendian、UTF-8六种编码的任意装换
  11. //程序作者:湖北师范学院计算机科学与技术学院王定桥
  12. //核心算法:根据不同编码特点向其他编码转换
  13. //测试结果:在Windows7VC6.0环境下测试通过
  14. //制作时间:2012-04-24
  15. //代码版权:代码公开供学习交流使用欢迎指正错误改善算法
  16. //-----------------------------------------------------------------------------------------------
  17. //Windows代码页
  18. typedefenumCodeType
  19. {
  20. CP_GB2312=936,
  21. CP_BIG5=950,
  22. CP_GBK=0
  23. }CodePages;
  24. //txt文件编码
  25. typedefenumTextCodeType
  26. {
  27. GB2312=0,
  28. BIG5=1,
  29. GBK=2,
  30. UTF8=3,
  31. UNICODE=4,
  32. UNICODEBIGENDIAN=5,
  33. DefaultCodeType=-1
  34. }TextCode;
  35. classCoder
  36. {
  37. public:
  38. Coder();
  39. virtual~Coder();
  40. public:
  41. //默认一次转换字节大小
  42. UINTPREDEFINEDSIZE;
  43. //指定转换时默认一次转换字节大小
  44. voidSetDefaultConvertSize(UINTnCount);
  45. //编码类型转换为字符串
  46. CStringCodeTypeToString(TextCodetc);
  47. //文件转到另一种文件
  48. BOOLFileToOtherFile(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo,TextCodetcCur=DefaultCodeType);
  49. //Unicode和Unicodebigendian文件之间转换
  50. BOOLUnicodeEndianFileConvert(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo);
  51. //多字节文件之间的转换
  52. BOOLMBFileToMBFile(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo,TextCodetcCur=DefaultCodeType);
  53. //Unicode和Unicodebigendian文件向多字节文件转换
  54. BOOLUnicodeFileToMBFile(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo);
  55. //多字节文件向Unicode和Unicodebigendian文件转换
  56. BOOLMBFileToUnicodeFile(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo,TextCodetcCur=DefaultCodeType);
  57. //获取文件编码类型
  58. TextCodeGetCodeType(CStringfilepath);
  59. //繁体中文BIG5转换成简体中文GB2312
  60. char*BIG5ToGB2312(constchar*szBIG5Str);
  61. //简体中文GB2312转换成繁体中文BIG5
  62. char*GB2312ToBIG5(constchar*szGB2312Str);
  63. //简繁中文GBK编码转换成简体中文GB2312
  64. char*GBKToGB2312(constchar*szGBkStr);
  65. //简体中文GB2312编码转换成简繁中文GBK
  66. char*GB2312ToGBK(constchar*szGB2312Str);
  67. //简繁中文GBK转换成繁体中文Big5
  68. char*GBKToBIG5(constchar*szGBKStr);
  69. //繁体中文BIG5转换到简繁中文GBK
  70. char*BIG5ToGBK(constchar*szBIG5Str);
  71. //宽字符串向多字节字符串转换
  72. char*WCharToMByte(UINTCodePage,LPCWSTRlpcwszSrcStr);
  73. //多字节字符串向宽字符串转换
  74. wchar_t*MByteToWChar(UINTCodePage,LPCSTRlpcszSrcStr);
  75. protected:
  76. //获取编码类型对应的代码页
  77. UINTGetCodePage(TextCodetccur);
  78. //多字节向多字节转换
  79. char*MByteToMByte(UINTCodePageCur,UINTCodePageTo,constchar*szSrcStr);
  80. //Unicode和Unicodebigendian字符串之间的转换
  81. voidUnicodeEndianConvert(LPWSTRlpwszstr);
  82. //文件头常量字节数组
  83. conststaticbyteUNICODEBOM[2];
  84. conststaticbyteUNICODEBEBOM[2];
  85. conststaticbyteUTF8BOM[3];
  86. };
  87. #endif//!defined(AFX_ENCODING_H__2AC955FB_9F8F_4871_9B77_C6C65730507F__INCLUDED_)
  1. //Coder.cpp:implementationoftheCoderclass.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include"stdafx.h"
  5. #include"Coder.h"
  6. #include"Encoding.h"
  7. #ifdef_DEBUG
  8. #undefTHIS_FILE
  9. staticcharTHIS_FILE[]=__FILE__;
  10. #definenewDEBUG_NEW
  11. #endif
  12. //////////////////////////////////////////////////////////////////////
  13. //Construction/Destruction
  14. //////////////////////////////////////////////////////////////////////
  15. //初始化文件头常量
  16. /*static*/constbyteCoder::UNICODEBOM[2]={0xFF,0xFE};
  17. /*static*/constbyteCoder::UNICODEBEBOM[2]={0xFE,0xFF};
  18. /*static*/constbyteCoder::UTF8BOM[3]={0xEF,0xBB,0xBF};
  19. Coder::Coder()
  20. {
  21. PREDEFINEDSIZE=2097152;//默认一次转换字节大小2M字节
  22. }
  23. Coder::~Coder()
  24. {
  25. }
  26. //繁体中文BIG5转换成简体中文GB2312
  27. char*Coder::BIG5ToGB2312(constchar*szBIG5Str)
  28. {
  29. CStringmsg;
  30. LCIDlcid=MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);
  31. wchar_t*szUnicodeBuff=MByteToWChar(CP_BIG5,szBIG5Str);
  32. char*szGB2312Buff=WCharToMByte(CP_GB2312,szUnicodeBuff);
  33. intnLength=LCMapString(lcid,LCMAP_SIMPLIFIED_CHINESE,szGB2312Buff,-1,NULL,0);
  34. char*pBuffer=newchar[nLength+1];
  35. if(!pBuffer)
  36. returnNULL;
  37. memset(pBuffer,0,sizeof(char)*(nLength+1));
  38. LCMapString(0x0804,LCMAP_SIMPLIFIED_CHINESE,szGB2312Buff,-1,pBuffer,nLength);
  39. delete[]szUnicodeBuff;
  40. delete[]szGB2312Buff;
  41. returnpBuffer;
  42. }
  43. //GB2312转GBK
  44. char*Coder::GB2312ToGBK(constchar*szGB2312Str)
  45. {
  46. intnStrLen=strlen(szGB2312Str);
  47. if(!nStrLen)
  48. returnNULL;
  49. LCIDwLCID=MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);
  50. intnReturn=LCMapString(wLCID,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,nStrLen,NULL,0);
  51. if(!nReturn)
  52. returnNULL;
  53. char*pcBuf=newchar[nReturn+1];
  54. if(!pcBuf)
  55. returnNULL;
  56. memset(pcBuf,0,sizeof(char)*(nReturn+1));
  57. wLCID=MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);
  58. LCMapString(wLCID,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,nReturn,pcBuf,nReturn);
  59. returnpcBuf;
  60. }
  61. //GBK转换成GB2312
  62. char*Coder::GBKToGB2312(constchar*szGBKStr)
  63. {
  64. intnStrLen=strlen(szGBKStr);
  65. if(!nStrLen)
  66. returnNULL;
  67. LCIDwLCID=MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_BIG5);
  68. intnReturn=LCMapString(wLCID,LCMAP_SIMPLIFIED_CHINESE,szGBKStr,nStrLen,NULL,0);
  69. if(!nReturn)
  70. returnNULL;
  71. char*pcBuf=newchar[nReturn+1];
  72. memset(pcBuf,0,sizeof(char)*(nReturn+1));
  73. wLCID=MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_BIG5);
  74. LCMapString(wLCID,LCMAP_SIMPLIFIED_CHINESE,szGBKStr,nReturn,pcBuf,nReturn);
  75. returnpcBuf;
  76. }
  77. //简繁中文GBK转换成繁体中文Big5
  78. char*Coder::GBKToBIG5(constchar*szGBKStr)
  79. {
  80. char*pTemp=NULL;
  81. char*pBuffer=NULL;
  82. pTemp=GBKToGB2312(szGBKStr);
  83. pBuffer=GB2312ToBIG5(pTemp);
  84. delete[]pTemp;
  85. returnpBuffer;
  86. }
  87. //繁体中文BIG5转换到简繁中文GBK
  88. char*Coder::BIG5ToGBK(constchar*szBIG5Str)
  89. {
  90. char*pTemp=NULL;
  91. char*pBuffer=NULL;
  92. pTemp=BIG5ToGB2312(szBIG5Str);
  93. pBuffer=GB2312ToGBK(pTemp);
  94. delete[]pTemp;
  95. returnpBuffer;
  96. }
  97. //简体中文GB2312转换成繁体中文BIG5
  98. char*Coder::GB2312ToBIG5(constchar*szGB2312Str)
  99. {
  100. LCIDlcid=MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);
  101. intnLength=LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,-1,NULL,0);
  102. char*pBuffer=newchar[nLength+1];
  103. if(!pBuffer)
  104. returnNULL;
  105. LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,-1,pBuffer,nLength);
  106. pBuffer[nLength]=0;
  107. wchar_t*pUnicodeBuff=MByteToWChar(CP_GB2312,pBuffer);
  108. char*pBIG5Buff=WCharToMByte(CP_BIG5,pUnicodeBuff);
  109. delete[]pBuffer;
  110. delete[]pUnicodeBuff;
  111. returnpBIG5Buff;
  112. }
  113. //获取文件编码类型
  114. //Unicode编码文件通过读取文件头判别
  115. //中文编码通过统计文件编码类别来判别判别次数最多为30次
  116. //中文编码的判别存在误差
  117. TextCodeCoder::GetCodeType(CStringfilepath)
  118. {
  119. CFilefile;
  120. bytebuf[3];//unsignedchar
  121. TextCodetctemp;
  122. if(file.Open(filepath,CFile::modeRead))
  123. {
  124. file.Read(buf,3);
  125. if(buf[0]==UTF8BOM[0]&&buf[1]==UTF8BOM[1]&&buf[2]==UTF8BOM[2])
  126. returnUTF8;
  127. else
  128. if(buf[0]==UNICODEBOM[0]&&buf[1]==UNICODEBOM[1])
  129. returnUNICODE;
  130. else
  131. if(buf[0]==UNICODEBEBOM[0]&&buf[1]==UNICODEBEBOM[1])
  132. returnUNICODEBIGENDIAN;
  133. else
  134. {
  135. inttime=30;
  136. while(file.Read(buf,2)&&time)
  137. {
  138. if((buf[0]>=176&&buf[0]<=247)&&(buf[1]>=160&&buf[1]<=254))
  139. tctemp=GB2312;
  140. else
  141. if((buf[0]>=129&&buf[0]<=255)&&((buf[1]>=64&&buf[1]<=126)||(buf[1]>=161&&buf[1]<=254)))
  142. tctemp=BIG5;
  143. else
  144. if((buf[0]>=129&&buf[0]<=254)&&(buf[1]>=64&&buf[1]<=254))
  145. tctemp=GBK;
  146. time--;
  147. file.Seek(100,CFile::current);//跳过一定字节利于统计全文
  148. }
  149. returntctemp;
  150. }
  151. }
  152. else
  153. returnGB2312;
  154. }
  155. //多字节文件转换为UNICODE、UNICODEbigendian文件
  156. BOOLCoder::MBFileToUnicodeFile(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo,TextCodetcCur)
  157. {
  158. TextCodecurtc;
  159. CFilefilesource,filesave;;
  160. char*pChSrc=NULL;
  161. char*pChTemp=NULL;
  162. wchar_t*pwChDes=NULL;
  163. DWORDfilelength,readlen,len;
  164. intbufferlen,strlength;
  165. UINTCodePage;
  166. //由于存在误差允许用户自定义转换
  167. if(tcCur!=DefaultCodeType)
  168. curtc=tcCur;
  169. else
  170. curtc=GetCodeType(filesourcepath);
  171. if(curtc>UTF8||tcTo<UNICODE||curtc==tcTo)
  172. returnFALSE;
  173. //源文件打开失败或者源文件无内容后者保存文件建立失败均返回转换失败
  174. if(!filesource.Open(filesourcepath,CFile::modeRead)||0==(filelength=filesource.GetLength()))
  175. returnFALSE;
  176. if(!filesave.Open(filesavepath,CFile::modeCreate|CFile::modeWrite))
  177. returnFALSE;
  178. //预分配内存分配失败则转换失败
  179. if(filelength<PREDEFINEDSIZE)
  180. bufferlen=filelength;
  181. else
  182. bufferlen=PREDEFINEDSIZE;
  183. pChSrc=newchar[bufferlen+1];
  184. if(!pChSrc)
  185. returnFALSE;
  186. //根据当前文件类别指定转换代码页
  187. switch(curtc)
  188. {
  189. caseGB2312:
  190. CodePage=CP_GB2312;
  191. break;
  192. caseGBK:
  193. CodePage=CP_GB2312;//特殊处理
  194. break;
  195. caseBIG5:
  196. CodePage=CP_BIG5;
  197. break;
  198. caseUTF8:
  199. CodePage=CP_UTF8;
  200. break;
  201. default:
  202. break;
  203. }
  204. //UTF8文件跳过文件
  205. if(UTF8==curtc)
  206. filesource.Seek(3*sizeof(byte),CFile::begin);
  207. //写入文件头
  208. if(UNICODEBIGENDIAN==tcTo)
  209. filesave.Write(&UNICODEBEBOM,2*sizeof(byte));
  210. else
  211. filesave.Write(&UNICODEBOM,2*sizeof(byte));
  212. //读取文件分段转换知道结束
  213. while(filelength>0)
  214. {
  215. memset(pChSrc,0,sizeof(char)*(bufferlen+1));
  216. if(filelength>PREDEFINEDSIZE)
  217. len=PREDEFINEDSIZE;
  218. else
  219. len=filelength;
  220. readlen=filesource.Read(pChSrc,len);
  221. if(!readlen)
  222. break;
  223. //GBK转换为GB2312处理
  224. if(GBK==curtc)
  225. {
  226. pChTemp=pChSrc;
  227. pChSrc=GBKToGB2312(pChSrc);
  228. }
  229. pwChDes=MByteToWChar(CodePage,pChSrc);
  230. if(pwChDes)
  231. {
  232. if(UNICODEBIGENDIAN==tcTo)
  233. UnicodeEndianConvert(pwChDes);
  234. strlength=wcslen(pwChDes)*2;//这里注意写入文件的长度
  235. filesave.Write(pwChDes,strlength);
  236. filesave.Flush();
  237. filelength-=readlen;
  238. }
  239. else
  240. break;
  241. }
  242. delete[]pChSrc;
  243. delete[]pChTemp;
  244. delete[]pwChDes;
  245. returnTRUE;
  246. }
  247. //
  248. wchar_t*Coder::MByteToWChar(UINTCodePage,LPCSTRlpcszSrcStr)
  249. {
  250. LPWSTRlpcwsStrDes=NULL;
  251. intlen=MultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,NULL,0);
  252. lpcwsStrDes=newwchar_t[len+1];
  253. if(!lpcwsStrDes)
  254. returnNULL;
  255. memset(lpcwsStrDes,0,sizeof(wchar_t)*(len+1));
  256. len=MultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,lpcwsStrDes,len);
  257. if(len)
  258. returnlpcwsStrDes;
  259. else
  260. {
  261. delete[]lpcwsStrDes;
  262. returnNULL;
  263. }
  264. }
  265. char*Coder::WCharToMByte(UINTCodePage,LPCWSTRlpcwszSrcStr)
  266. {
  267. char*lpszDesStr=NULL;
  268. intlen=WideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,NULL,0,NULL,NULL);
  269. lpszDesStr=newchar[len+1];
  270. memset(lpszDesStr,0,sizeof(char)*(len+1));
  271. if(!lpszDesStr)
  272. returnNULL;
  273. len=WideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,lpszDesStr,len,NULL,NULL);
  274. if(len)
  275. returnlpszDesStr;
  276. else
  277. {
  278. delete[]lpszDesStr;
  279. returnNULL;
  280. }
  281. }
  282. //Unicode和Unicodebigendian之间字节序的转换
  283. voidCoder::UnicodeEndianConvert(LPWSTRlpwszstr)
  284. {
  285. wchar_twchtemp[2];
  286. longindex;
  287. intlen=wcslen(lpwszstr);
  288. if(!len)
  289. return;
  290. //交换高低字节直到遇到结束符
  291. index=0;
  292. while(index<len)
  293. {
  294. wchtemp[0]=lpwszstr[index];
  295. wchtemp[1]=lpwszstr[index+1];
  296. unsignedcharhigh,low;
  297. high=(wchtemp[0]&0xFF00)>>8;
  298. low=wchtemp[0]&0x00FF;
  299. wchtemp[0]=(low<<8)|high;
  300. high=(wchtemp[1]&0xFF00)>>8;
  301. low=wchtemp[1]&0x00FF;
  302. wchtemp[1]=(low<<8)|high;
  303. lpwszstr[index]=wchtemp[0];
  304. lpwszstr[index+1]=wchtemp[1];
  305. index+=2;
  306. }
  307. }
  308. //Unicode和Unicodebigendian文件向多字节文件转换
  309. BOOLCoder::UnicodeFileToMBFile(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo)
  310. {
  311. TextCodecurtc;
  312. CFilefilesource,filesave;;
  313. char*pChDes=NULL;
  314. char*pChTemp=NULL;
  315. wchar_t*pwChSrc=NULL;
  316. DWORDfilelength,readlen,len;
  317. intbufferlen,strlength;
  318. UINTCodePage;
  319. curtc=GetCodeType(filesourcepath);
  320. //文件转换类型错误则转换失败
  321. if(curtc<=UTF8||tcTo>UTF8||curtc==tcTo)
  322. returnFALSE;
  323. //源文件打开失败或者源文件无内容后者保存文件建立失败均转换失败
  324. if(!filesource.Open(filesourcepath,CFile::modeRead)||0==(filelength=filesource.GetLength()))
  325. returnFALSE;
  326. if(!filesave.Open(filesavepath,CFile::modeCreate|CFile::modeWrite))
  327. returnFALSE;
  328. //预分配内存分配失败则转换失败
  329. if(filelength<PREDEFINEDSIZE)
  330. bufferlen=filelength;
  331. else
  332. bufferlen=PREDEFINEDSIZE;
  333. pwChSrc=newwchar_t[(bufferlen/2)+1];
  334. if(!pwChSrc)
  335. returnFALSE;
  336. //预先决定代码页
  337. switch(tcTo)
  338. {
  339. caseGB2312:
  340. CodePage=CP_GB2312;
  341. break;
  342. caseGBK:
  343. CodePage=CP_GB2312;//特殊处理
  344. break;
  345. caseBIG5:
  346. CodePage=CP_GB2312;//特殊处理
  347. break;
  348. caseUTF8:
  349. CodePage=CP_UTF8;
  350. break;
  351. default:
  352. break;
  353. }
  354. filesource.Seek(sizeof(wchar_t),CFile::begin);
  355. while(filelength>0)
  356. {
  357. memset(pwChSrc,0,sizeof(wchar_t)*((bufferlen/2)+1));
  358. if(filelength>PREDEFINEDSIZE)
  359. len=PREDEFINEDSIZE;
  360. else
  361. len=filelength;
  362. readlen=filesource.Read(pwChSrc,len);
  363. if(!readlen)
  364. break;
  365. if(UNICODEBIGENDIAN==curtc)
  366. UnicodeEndianConvert(pwChSrc);
  367. pChDes=WCharToMByte(CodePage,pwChSrc);
  368. //GBK无法直接转换BIG5直接转换会产生错误二者均先转到GB2312然后再转到目的类型
  369. if(GBK==tcTo)
  370. {
  371. pChTemp=pChDes;
  372. pChDes=GB2312ToGBK(pChDes);
  373. }
  374. if(BIG5==tcTo)
  375. {
  376. pChTemp=pChDes;
  377. pChDes=GB2312ToBIG5(pChDes);
  378. }
  379. if(pChDes)
  380. {
  381. strlength=strlen(pChDes);
  382. filesave.Write(pChDes,strlength);
  383. filesave.Flush();
  384. filelength-=readlen;
  385. }
  386. else
  387. break;
  388. }
  389. delete[]pChDes;
  390. delete[]pChTemp;
  391. delete[]pwChSrc;
  392. returnTRUE;
  393. }
  394. //多字节文件转为多字节文件
  395. //多字节转为多字节时,一般先转为UNICODE类型,再转换到指定目的类型,实行两次转换
  396. BOOLCoder::MBFileToMBFile(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo,TextCodetcCur)
  397. {
  398. BOOLbret=FALSE;
  399. TextCodecurtc;
  400. CFilefilesource,filesave;
  401. char*pChDes=NULL;
  402. char*pChSrc=NULL;
  403. DWORDfilelength,readlen,len;
  404. intbufferlen,strlength;
  405. UINTCodePageCur,CodePageTo;
  406. //由于存在误差允许用户自定义转换
  407. if(DefaultCodeType!=tcCur)
  408. curtc=tcCur;
  409. else
  410. curtc=GetCodeType(filesourcepath);
  411. //转换类型错误则返回转换失败
  412. if(curtc>UTF8||tcTo>UTF8||curtc==tcTo)
  413. returnFALSE;
  414. //源文件打开失败或者源文件无内容后者保存文件建立失败均返回转换失败
  415. if(!filesource.Open(filesourcepath,CFile::modeRead)||0==(filelength=filesource.GetLength()))
  416. returnFALSE;
  417. if(!filesave.Open(filesavepath,CFile::modeCreate|CFile::modeWrite))
  418. returnFALSE;
  419. //预分配内存分配失败则转换失败
  420. if(filelength<PREDEFINEDSIZE)
  421. bufferlen=filelength;
  422. else
  423. bufferlen=PREDEFINEDSIZE;
  424. pChSrc=newchar[bufferlen+1];
  425. if(!pChSrc)
  426. returnFALSE;
  427. if(UTF8==curtc)
  428. filesource.Seek(3*sizeof(byte),CFile::begin);
  429. CodePageCur=GetCodePage(curtc);
  430. CodePageTo=GetCodePage(tcTo);
  431. while(filelength>0)
  432. {
  433. memset(pChSrc,0,sizeof(char)*(bufferlen+1));
  434. if(filelength>PREDEFINEDSIZE)
  435. len=PREDEFINEDSIZE;
  436. else
  437. len=filelength;
  438. readlen=filesource.Read(pChSrc,len);
  439. if(!readlen)
  440. break;
  441. pChDes=MByteToMByte(CodePageCur,CodePageTo,pChSrc);
  442. if(pChDes)
  443. {
  444. strlength=strlen(pChDes);
  445. filesave.Write(pChDes,strlength);
  446. filelength-=readlen;
  447. }
  448. else
  449. break;
  450. }
  451. delete[]pChSrc;
  452. delete[]pChDes;
  453. returnTRUE;
  454. }
  455. //Unicode和Unicodebigendian文件之间转换
  456. BOOLCoder::UnicodeEndianFileConvert(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo)
  457. {
  458. TextCodecurtc=GetCodeType(filesourcepath);
  459. if(curtc!=UNICODE&&curtc!=UNICODEBIGENDIAN)
  460. returnFALSE;
  461. if(curtc==tcTo)
  462. returnFALSE;
  463. CFilefilesource,filesave;;
  464. wchar_t*pwChDes;
  465. DWORDlength;
  466. if(!filesource.Open(filesourcepath,CFile::modeRead)||!filesave.Open(filesavepath,CFile::modeCreate|CFile::modeWrite))
  467. returnFALSE;
  468. length=filesource.GetLength();
  469. if(!length)
  470. returnFALSE;
  471. pwChDes=newwchar_t[(length/2)+1];
  472. if(!pwChDes)
  473. returnFALSE;
  474. memset(pwChDes,0,sizeof(wchar_t)*((length/2)+1));
  475. filesource.Read(pwChDes,length);
  476. UnicodeEndianConvert(pwChDes);
  477. length=wcslen(pwChDes)*2;
  478. if(UNICODE==tcTo)
  479. filesave.Write(&UNICODEBOM,2*sizeof(byte));
  480. else
  481. filesave.Write(&UNICODEBEBOM,2*sizeof(byte));
  482. filesave.Write(pwChDes,length);
  483. filesave.Flush();
  484. delete[]pwChDes;
  485. returnTRUE;
  486. }
  487. //文件转到另一种文件
  488. //6种格式文件两两转换共计30种转换
  489. BOOLCoder::FileToOtherFile(CStringfilesourcepath,CStringfilesavepath,TextCodetcTo,TextCodetcCur)
  490. {
  491. TextCodecurtc;
  492. BOOLbret=FALSE;
  493. if(DefaultCodeType!=tcCur)
  494. curtc=tcCur;
  495. else
  496. curtc=GetCodeType(filesourcepath);
  497. if(curtc==tcTo)
  498. returnFALSE;
  499. //UNICODE和UNICODEbigendian文件之间转换共2种
  500. if(curtc>=UNICODE&&tcTo>=UNICODE)
  501. bret=UnicodeEndianFileConvert(filesourcepath,filesavepath,tcTo);
  502. else
  503. //多字节文件向UNICODE和UNICODEbigendian文件之间转换共8种
  504. if(curtc<UNICODE&&tcTo>=UNICODE)
  505. bret=MBFileToUnicodeFile(filesourcepath,filesavepath,tcTo,curtc);
  506. else
  507. //UNICODE和UNICODEbigendian文件向多字节文件转换共8种
  508. if(curtc>=UNICODE&&tcTo<UNICODE)
  509. bret=UnicodeFileToMBFile(filesourcepath,filesavepath,tcTo);
  510. else
  511. //多字节文件之间转换共12种
  512. if(curtc<UNICODE&&tcTo<UNICODE)
  513. bret=MBFileToMBFile(filesourcepath,filesavepath,tcTo,curtc);
  514. returnbret;
  515. }
  516. //编码类型转换为字符串
  517. CStringCoder::CodeTypeToString(TextCodetc)
  518. {
  519. CStringstrtype;
  520. switch(tc)
  521. {
  522. caseGB2312:
  523. strtype=_T("GB2312");
  524. break;
  525. caseBIG5:
  526. strtype=_T("Big5");
  527. break;
  528. caseGBK:
  529. strtype=_T("GBK");
  530. break;
  531. caseUTF8:
  532. strtype=_T("UTF-8");
  533. break;
  534. caseUNICODE:
  535. strtype=_T("Unicode");
  536. break;
  537. caseUNICODEBIGENDIAN:
  538. strtype=_T("Unicodebigendian");
  539. break;
  540. }
  541. returnstrtype;
  542. }
  543. //多字节向多字节转换
  544. char*Coder::MByteToMByte(UINTCodePageCur,UINTCodePageTo,constchar*szSrcStr)
  545. {
  546. char*pchDes=NULL;
  547. char*pchTemp=NULL;
  548. wchar_t*pwchtemp=NULL;
  549. //三种中文编码之间转换
  550. if(CodePageCur!=CP_UTF8&&CodePageTo!=CP_UTF8)
  551. {
  552. switch(CodePageCur)
  553. {
  554. caseCP_GB2312:
  555. {
  556. if(CP_BIG5==CodePageTo)
  557. pchDes=GB2312ToBIG5(szSrcStr);
  558. else
  559. pchDes=GB2312ToGBK(szSrcStr);
  560. break;
  561. }
  562. caseCP_BIG5:
  563. {
  564. if(CP_GB2312==CodePageTo)
  565. pchDes=BIG5ToGB2312(szSrcStr);
  566. else
  567. pchDes=BIG5ToGBK(szSrcStr);
  568. break;
  569. }
  570. caseCP_GBK:
  571. {
  572. if(CP_GB2312==CodePageTo)
  573. pchDes=GBKToGB2312(szSrcStr);
  574. else
  575. pchDes=GBKToBIG5(szSrcStr);
  576. break;
  577. }
  578. }
  579. }
  580. else
  581. {//从UTF-8转到其他多字节直接转到GB2312其他形式用GB2312做中间形式
  582. if(CP_UTF8==CodePageCur)
  583. {
  584. pwchtemp=MByteToWChar(CodePageCur,szSrcStr);
  585. if(CP_GB2312==CodePageTo)
  586. {
  587. pchDes=WCharToMByte(CP_GB2312,pwchtemp);
  588. }
  589. else
  590. {
  591. pchTemp=WCharToMByte(CP_GB2312,pwchtemp);
  592. if(CP_GBK==CodePageTo)
  593. pchDes=GB2312ToGBK(pchTemp);
  594. else
  595. pchDes=GB2312ToBIG5(pchTemp);
  596. }
  597. }
  598. //从其他多字节转到UTF-8
  599. else
  600. {
  601. if(CP_GBK==CodePageCur)
  602. {
  603. pchTemp=GBKToGB2312(szSrcStr);
  604. pwchtemp=MByteToWChar(CP_GB2312,pchTemp);
  605. }
  606. else
  607. pwchtemp=MByteToWChar(CodePageCur,szSrcStr);
  608. pchDes=WCharToMByte(CodePageTo,pwchtemp);
  609. }
  610. }
  611. delete[]pchTemp;
  612. delete[]pwchtemp;
  613. returnpchDes;
  614. }
  615. //获取编码类型对应的代码页
  616. UINTCoder::GetCodePage(TextCodetccur)
  617. {
  618. UINTCodePage;
  619. switch(tccur)
  620. {
  621. caseGB2312:
  622. CodePage=CP_GB2312;
  623. break;
  624. caseBIG5:
  625. CodePage=CP_BIG5;
  626. break;
  627. caseGBK:
  628. CodePage=CP_GBK;
  629. break;
  630. caseUTF8:
  631. CodePage=CP_UTF8;
  632. break;
  633. caseUNICODEBIGENDIAN:
  634. caseUNICODE:
  635. break;
  636. }
  637. returnCodePage;
  638. }
  639. //指定转换时默认一次转换字节大小
  640. voidCoder::SetDefaultConvertSize(UINTnCount)
  641. {
  642. if(nCount!=0)
  643. PREDEFINEDSIZE=nCount;
  644. }
3.运行效果 在win7 VC 6.0下测试六种编码的转换测试通过,30个方向的转换如下图所示:

测试程序运行效果如下图所示:


GB2312转换到GBK编码效果如下图所示:



UTF-8转换到Big5编码的效果如下图所示:


本文代码及转码程序下载http://download.csdn.net/user/ziyuanxiazai123

4.尚未解决的问题

(1)LCMapString函数的理解还不完全熟悉,其中参数偏多,理解需要一定基础知识。

(2)为什么记事本程序的转码后存在些乱码,乱码是正确的吗?因为我的程序使用了中间过渡形式,因此没有任何乱码。

(3)是否有更简单和清晰的方式实现编码转换,待进一步研究。
分享到:
评论

相关推荐

    中文编码规则,一网打尽

    在详细解读“中文编码规则,一网打尽”这一主题之前,我们首先需要明确几个关键概念,包括字符编码、Unicode、ASCII、以及中文编码的特殊规则。这些概念对于理解文本所描述的中文编码规则至关重要。 首先,字符编码...

    qcp转换MP3 QCP转换wav 手机录音转换任意格式

    6. **联系作者**:"双击联系作者.url"可能是一个快捷方式,允许用户直接联系到软件的开发者,获取技术支持或报告问题。这是获取官方帮助的重要途径。 综上所述,QCP格式的音频文件转换涉及到特定的工具和流程,用户...

    foxfire编码识别编译版 - byvoid,

    foxfire编码识别编译版 - byvoid,我只是打包编译了一下. 编码问题一网打尽 - wangjieest的专栏 - http://blog.csdn.net/wangjieest/article/details/8097035

    旋风转换器v6.8.0.0免费安装版

    旋风转换器是文件格式转换工具,是专业智能的办公软件,支持上百种文件格式转换与操作,将你的办公需求一网打尽。能够转换多种格式互相转换,还能够进行图片压缩。 软件特色 支持pdf转word,pd

    一网打尽Android-UI

    本文将深入探讨“一网打尽Android-UI”中的关键知识点,包括各种UI组件的使用和功能。 1. **关于Android的一些设计**: Android的设计原则强调简洁、直观和一致。开发者应遵循Material Design指南,提供清晰的层次...

    功能超强的网络流媒体地址嗅探工具__酷抓coojah_6.8.193.0614终结版

    +全新推出简体中文、英文、繁体中文三个语言版本。欢迎推荐给使用这些语言有朋友 +独家支持RTMP协议FLV流媒体的抓取 *修正本地缓存另存的BUG,同时修改为“快速保存” 2009-01-08 酷抓6 Beta Build090108 *强制退出...

    一网打尽18种主流数据库:12种SQL+6种NoSQL.doc

    一网打尽18种主流数据库:12种SQL+6种NoSQL

    影音转霸|视频加水印合并转换格式一网打尽

    只需选择输入和输出格式,软件会自动进行编码优化,确保转换后的视频质量和原始文件相差无几。 此外,影音转霸的用户界面友好,操作流程直观,即使是对电脑操作不熟悉的用户也能快速上手。软件还提供了批量处理功能...

    艾奇MTS视频格式转换器绿色特别版

    一款很专业视频个转换器软件,好多专业视频制作网站都是用这个软件,支持视频、音频、DVD格式转换的终极解决方案。它可以高速转换任何视频格式、音频格式、DVD,输出100多种格式的音视频格式,RM、AVI、WMV、MP4、...

    八木-双菱-长城-各种图片等等》》一网打尽

    今天我们要探究的,正是这样一个涵盖“八木”、“双菱”和“长城”等关键字的图片资源压缩包,它以“一网打尽”的形式,展示了这些主题相关的多样图片内容。 首先,我们必须明白“八木”、“双菱”和“长城”在这里...

    一网打尽2001-2022上市公司风险承担水平大合集,附赠原始数据、测算代码!

    业风险承担水平大合集,十余种衡量方法的测算结果一网打尽,附赠测算过程的所有原始数 据、操作代码和10篇权威期刊的参考文献(我本人也有资本市场和公司治理的项目,个人 认为对选题和方向具有极高的价值),一定让...

    AVI MPEG WMV RM to MP3 Converter

    "AVI MPEG WMV RM to MP3 Converter"正是这样一款能够解决多种音频格式转换问题的软件,它将各种音频格式一网打尽,让用户告别因格式不兼容带来的不便。 AVI、MPEG、WMV和RM是常见的视频格式,它们内含的音频部分...

    一网打尽:四级考试历年真题集(2016年12月-2023年6月)

    “一网打尽:四级考试历年真题集(2016年12月-2023年6月)” 想要顺利拿下英语四级考试?别再东拼西凑找资料了!我们为您精心整理了从2016年12月至2023年6月的所有四级真题,一网打尽,不留死角。这不仅仅是一本...

    ultra video converter

    无论是AVI、DivX、XviD这类常见的编码格式,还是MPEG、DAT、WMV、ASF等多媒体容器格式,甚至包括网络上流行的RM、RMVB、MOV、QT以及新兴的MP4格式,这款软件都能一网打尽,实现无缝转换。 首先,我们来详细了解AVI...

    一网打尽1990-2022绿色专利绿色创新数据大合集,涵盖上市公司和省市级所有类型!

    【一网打尽绿色创新,数据大合集值得信赖】 附件为我国1990-2022绿色专利绿 色创新数据大合集,又称绿色专利(绿色创新)数据库。总计上百万个观测值,几十张数据 表格,一网打尽涉及绿色专利和绿色创新的所有数据。...

    舟舟PHP影视系统_2.0

    ·海量资源库,完全免费采集(快播,迅播,web9,皮皮,高清视频)一网打尽 --------------------------------------- 为什么选择 舟舟影视系统 --------------------------------------- 1.卓越的访问速度和负载...

    考研必考词汇辨析一网打尽

    6. exclude v. 排斥、排除,不包括在内。例如:“The restaurant excludes anyone who is not properly dressed from entering.”(衣冠不整者不得进入该餐馆。) 7. extinguish v. 熄灭(火),使沉默或暗淡。例如...

Global site tag (gtag.js) - Google Analytics