自助建网站信息发布企业,网站被k怎么恢复,景观效果图用什么软件制作,域名服务器如何申请一网打尽中文编码转换——6种编码30个方向的转换 1.问题提出 在学编程序时#xff0c;曾经有人问过“你可以编一个记事本程序吗?”当时很不屑一顾#xff0c;但是随着学习MFC的深入#xff0c;了解到记事本程序也并非易事#xff0c;难点就是四种编码之间的转换。
对于编…一网打尽中文编码转换——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。
以上两个函数可以完成大部分的字符串转换可以将其封装成多字节和宽字节之间的转换函数:[cpp] view plaincopyprint?wchar_t* Coder::MByteToWChar(UINT CodePage,LPCSTR lpcszSrcStr) { LPWSTR lpcwsStrDesNULL; int lenMultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,NULL,0); lpcwsStrDesnew wchar_t[len1]; if(!lpcwsStrDes) return NULL; memset(lpcwsStrDes,0,sizeof(wchar_t)*(len1)); lenMultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,lpcwsStrDes,len); if(len) return lpcwsStrDes; else { delete[] lpcwsStrDes; return NULL; } } char* Coder::WCharToMByte(UINT CodePage,LPCWSTR lpcwszSrcStr) { char* lpszDesStrNULL; int lenWideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,NULL,0,NULL,NULL); lpszDesStrnew char[len1]; memset(lpszDesStr,0,sizeof(char)*(len1)); if(!lpszDesStr) return NULL; lenWideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,lpszDesStr,len,NULL,NULL); if(len) return lpszDesStr; else { delete[] lpszDesStr; return NULL; } }
c.LCMapString
依赖于本地机器的字符转换函数尤其是中文编码在转换时要依赖于本地机器
直接利用上述a、b中叙述的函数会产生错误,例如直接从GB2312转换到Big5利用MultiByteToWideChar函数将GB2312转换到Unicode字符串然后从Unicode字符串利用函数WideCharToMultiByte转换成Big5,将会发生错误错误的结果如下图所示:
因此中文编码转换时适当使用LCMapString函数才能完成正确的转换.
例如:[cpp] view plaincopyprint?//简体中文 GB2312 转换成 繁体中文BIG5 char* Coder::GB2312ToBIG5(const char* szGB2312Str) { LCID lcid MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC); int nLength LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,-1,NULL,0); char* pBuffernew char[nLength1]; if(!pBuffer) return NULL; LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,-1,pBuffer,nLength); pBuffer[nLength]0; wchar_t* pUnicodeBuff MByteToWChar(CP_GB2312,pBuffer); char* pBIG5Buff WCharToMByte(CP_BIG5,pUnicodeBuff); delete[] pBuffer; delete[] pUnicodeBuff; return pBIG5Buff; } (5)编码实现
实现Coder类完成编码转换工作.
Coder类的代码清单如下:[cpp] view plaincopyprint?// Coder.h: interface for the Coder class. // // #if !defined(AFX_ENCODING_H__2AC955FB_9F8F_4871_9B77_C6C65730507F__INCLUDED_) #define AFX_ENCODING_H__2AC955FB_9F8F_4871_9B77_C6C65730507F__INCLUDED_ #if _MSC_VER 1000 #pragma once #endif // _MSC_VER 1000 //----------------------------------------------------------------------------------------------- //程序用途实现GB2312、big5、GBK、Unicode、Unicode big endian、UTF-8六种编码的任意装换 //程序作者湖北师范学院计算机科学与技术学院 王定桥 //核心算法根据不同编码特点向其他编码转换 //测试结果:在Windows7 VC6.0环境下测试通过 //制作时间2012-04-24 //代码版权:代码公开供学习交流使用 欢迎指正错误 改善算法 //----------------------------------------------------------------------------------------------- //Windows代码页 typedef enum CodeType { CP_GB2312936, CP_BIG5950, CP_GBK0 }CodePages; //txt文件编码 typedef enum TextCodeType { GB23120, BIG51, GBK2, UTF83, UNICODE4, UNICODEBIGENDIAN5, DefaultCodeType-1 }TextCode; class Coder { public: Coder(); virtual ~Coder(); public: //默认一次转换字节大小 UINT PREDEFINEDSIZE; //指定转换时默认一次转换字节大小 void SetDefaultConvertSize(UINT nCount); //编码类型转换为字符串 CString CodeTypeToString(TextCode tc); //文件转到另一种文件 BOOL FileToOtherFile(CString filesourcepath, CString filesavepath,TextCode tcTo,TextCode tcCurDefaultCodeType); //Unicode 和Unicode big endian文件之间转换 BOOL UnicodeEndianFileConvert(CString filesourcepath, CString filesavepath,TextCode tcTo); //多字节文件之间的转换 BOOL MBFileToMBFile(CString filesourcepath, CString filesavepath,TextCode tcTo,TextCode tcCurDefaultCodeType); //Unicode和Unicode big endian文件向多字节文件转换 BOOL UnicodeFileToMBFile(CString filesourcepath, CString filesavepath,TextCode tcTo); //多字节文件向Unicode和Unicode big endian文件转换 BOOL MBFileToUnicodeFile(CString filesourcepath,CString filesavepath,TextCode tcTo,TextCode tcCurDefaultCodeType); //获取文件编码类型 TextCode GetCodeType(CString filepath); //繁体中文BIG5 转换成 简体中文 GB2312 char* BIG5ToGB2312(const char* szBIG5Str); //简体中文 GB2312 转换成 繁体中文BIG5 char* GB2312ToBIG5(const char* szGB2312Str); //简繁中文GBK编码转换成简体中文GB2312 char* GBKToGB2312(const char *szGBkStr); //简体中文GB2312编码转换成简繁中文GBK char* GB2312ToGBK(const char *szGB2312Str); //简繁中文GBK转换成繁体中文Big5 char* GBKToBIG5(const char *szGBKStr); //繁体中文BIG5转换到简繁中文GBK char* BIG5ToGBK(const char *szBIG5Str); //宽字符串向多字节字符串转换 char* WCharToMByte(UINT CodePage,LPCWSTR lpcwszSrcStr); //多字节字符串向宽字符串转换 wchar_t* MByteToWChar(UINT CodePage,LPCSTR lpcszSrcStr); protected: //获取编码类型对应的代码页 UINT GetCodePage(TextCode tccur); //多字节向多字节转换 char* MByteToMByte(UINT CodePageCur,UINT CodePageTo,const char* szSrcStr); //Unicode和Unicode big endian字符串之间的转换 void UnicodeEndianConvert(LPWSTR lpwszstr); //文件头常量字节数组 const static byte UNICODEBOM[2]; const static byte UNICODEBEBOM[2]; const static byte UTF8BOM[3]; }; #endif // !defined(AFX_ENCODING_H__2AC955FB_9F8F_4871_9B77_C6C65730507F__INCLUDED_) [cpp] view plaincopyprint?// Coder.cpp: implementation of the Coder class. // // #include stdafx.h #include Coder.h #include Encoding.h #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]__FILE__; #define new DEBUG_NEW #endif // // Construction/Destruction // //初始化文件头常量 /*static*/ const byte Coder::UNICODEBOM[2]{0xFF,0xFE}; /*static*/ const byte Coder::UNICODEBEBOM[2]{0xFE,0xFF}; /*static*/ const byte Coder::UTF8BOM[3]{0xEF,0xBB,0xBF}; Coder::Coder() { PREDEFINEDSIZE2097152;//默认一次转换字节大小 2M字节 } Coder::~Coder() { } //繁体中文BIG5 转换成 简体中文 GB2312 char* Coder::BIG5ToGB2312(const char* szBIG5Str) { CString msg; LCID lcid MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC); wchar_t* szUnicodeBuff MByteToWChar(CP_BIG5,szBIG5Str); char* szGB2312Buff WCharToMByte(CP_GB2312,szUnicodeBuff); int nLength LCMapString(lcid,LCMAP_SIMPLIFIED_CHINESE, szGB2312Buff,-1,NULL,0); char* pBuffer new char[nLength 1]; if(!pBuffer) return NULL; memset(pBuffer,0,sizeof(char)*(nLength1)); LCMapString(0x0804,LCMAP_SIMPLIFIED_CHINESE,szGB2312Buff,-1,pBuffer,nLength); delete[] szUnicodeBuff; delete[] szGB2312Buff; return pBuffer; } // GB2312 转 GBK char* Coder::GB2312ToGBK(const char *szGB2312Str) { int nStrLen strlen(szGB2312Str); if(!nStrLen) return NULL; LCID wLCID MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_CHINESE_PRC); int nReturn LCMapString(wLCID, LCMAP_TRADITIONAL_CHINESE, szGB2312Str, nStrLen, NULL, 0); if(!nReturn) return NULL; char *pcBuf new char[nReturn 1]; if(!pcBuf) return NULL; memset(pcBuf,0,sizeof(char)*(nReturn 1)); wLCID MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_CHINESE_PRC); LCMapString(wLCID, LCMAP_TRADITIONAL_CHINESE, szGB2312Str, nReturn, pcBuf, nReturn); return pcBuf; } // GBK 转换成 GB2312 char* Coder::GBKToGB2312(const char *szGBKStr) { int nStrLen strlen(szGBKStr); if(!nStrLen) return NULL; LCID wLCID MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_CHINESE_BIG5); int nReturn LCMapString(wLCID, LCMAP_SIMPLIFIED_CHINESE, szGBKStr, nStrLen, NULL, 0); if(!nReturn) return NULL; char *pcBuf new char[nReturn 1]; memset(pcBuf,0,sizeof(char)*(nReturn 1)); wLCID MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_CHINESE_BIG5); LCMapString(wLCID, LCMAP_SIMPLIFIED_CHINESE, szGBKStr, nReturn, pcBuf, nReturn); return pcBuf; } //简繁中文GBK转换成繁体中文Big5 char* Coder::GBKToBIG5(const char *szGBKStr) { char *pTempNULL; char *pBufferNULL; pTempGBKToGB2312(szGBKStr); pBufferGB2312ToBIG5(pTemp); delete[] pTemp; return pBuffer; } //繁体中文BIG5转换到简繁中文GBK char* Coder::BIG5ToGBK(const char *szBIG5Str) { char *pTempNULL; char *pBufferNULL; pTempBIG5ToGB2312(szBIG5Str); pBufferGB2312ToGBK(pTemp); delete[] pTemp; return pBuffer; } //简体中文 GB2312 转换成 繁体中文BIG5 char* Coder::GB2312ToBIG5(const char* szGB2312Str) { LCID lcid MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC); int nLength LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,-1,NULL,0); char* pBuffernew char[nLength1]; if(!pBuffer) return NULL; LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGB2312Str,-1,pBuffer,nLength); pBuffer[nLength]0; wchar_t* pUnicodeBuff MByteToWChar(CP_GB2312,pBuffer); char* pBIG5Buff WCharToMByte(CP_BIG5,pUnicodeBuff); delete[] pBuffer; delete[] pUnicodeBuff; return pBIG5Buff; } //获取文件编码类型 //Unicode编码文件通过读取文件头判别 //中文编码通过统计文件编码类别来判别 判别次数最多为30次 //中文编码的判别存在误差 TextCode Coder::GetCodeType(CString filepath) { CFile file; byte buf[3];//unsigned char TextCode tctemp; if(file.Open(filepath,CFile::modeRead)) { file.Read(buf,3); if(buf[0]UTF8BOM[0] buf[1]UTF8BOM[1] buf[2]UTF8BOM[2]) return UTF8; else if(buf[0]UNICODEBOM[0] buf[1]UNICODEBOM[1] ) return UNICODE ; else if(buf[0]UNICODEBEBOM[0] buf[1]UNICODEBEBOM[1] ) return UNICODEBIGENDIAN; else { int time30; while(file.Read(buf,2) time ) { if ( (buf[0]176 buf[0]247) (buf[1]160 buf[1]254) ) tctempGB2312; else if ( (buf[0]129 buf[0]255) ( ( buf[1]64 buf[1]126) || ( buf[1]161 buf[1]254) ) ) tctempBIG5; else if ( (buf[0]129 buf[0] 254) (buf[1]64 buf[1]254)) tctempGBK; time--; file.Seek(100,CFile::current);//跳过一定字节 利于统计全文 } return tctemp; } } else return GB2312; } //多字节文件转换为UNICODE、UNICODE big endian文件 BOOL Coder::MBFileToUnicodeFile(CString filesourcepath, CString filesavepath,TextCode tcTo,TextCode tcCur) { TextCode curtc; CFile filesource,filesave;; char *pChSrcNULL; char *pChTempNULL; wchar_t *pwChDesNULL; DWORD filelength,readlen,len; int bufferlen,strlength; UINT CodePage; //由于存在误差 允许用户自定义转换 if(tcCur!DefaultCodeType) curtctcCur; else curtcGetCodeType(filesourcepath); if(curtcUTF8 || tcTo UNICODE || curtctcTo) return FALSE; //源文件打开失败或者源文件无内容 后者保存文件建立失败 均返回转换失败 if(!filesource.Open(filesourcepath,CFile::modeRead) || 0(filelengthfilesource.GetLength())) return FALSE; if( !filesave.Open(filesavepath,CFile::modeCreate|CFile::modeWrite)) return FALSE; //预分配内存 分配失败则转换失败 if(filelengthPREDEFINEDSIZE) bufferlenfilelength; else bufferlenPREDEFINEDSIZE; pChSrcnew char[bufferlen1]; if(!pChSrc) return FALSE; //根据当前文件类别指定转换代码页 switch(curtc) { case GB2312: CodePageCP_GB2312; break; case GBK: CodePageCP_GB2312;//特殊处理 break; case BIG5: CodePageCP_BIG5; break; case UTF8: CodePageCP_UTF8; break; default: break; } //UTF8文件跳过文件 if(UTF8curtc) filesource.Seek(3*sizeof(byte),CFile::begin); //写入文件头 if(UNICODEBIGENDIANtcTo) filesave.Write(UNICODEBEBOM,2*sizeof(byte)); else filesave.Write(UNICODEBOM,2*sizeof(byte)); //读取文件 分段转换知道结束 while(filelength0) { memset(pChSrc,0, sizeof(char)*(bufferlen1)); if(filelengthPREDEFINEDSIZE) lenPREDEFINEDSIZE; else lenfilelength; readlenfilesource.Read(pChSrc,len); if(!readlen) break; //GBK转换为GB2312处理 if(GBKcurtc) { pChTemppChSrc; pChSrcGBKToGB2312(pChSrc); } pwChDesMByteToWChar(CodePage,pChSrc); if(pwChDes) { if(UNICODEBIGENDIANtcTo) UnicodeEndianConvert(pwChDes); strlengthwcslen(pwChDes)*2;//这里注意写入文件的长度 filesave.Write(pwChDes,strlength); filesave.Flush(); filelength-readlen; } else break; } delete[] pChSrc; delete[] pChTemp; delete[] pwChDes; return TRUE; } // wchar_t* Coder::MByteToWChar(UINT CodePage,LPCSTR lpcszSrcStr) { LPWSTR lpcwsStrDesNULL; int lenMultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,NULL,0); lpcwsStrDesnew wchar_t[len1]; if(!lpcwsStrDes) return NULL; memset(lpcwsStrDes,0,sizeof(wchar_t)*(len1)); lenMultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,lpcwsStrDes,len); if(len) return lpcwsStrDes; else { delete[] lpcwsStrDes; return NULL; } } char* Coder::WCharToMByte(UINT CodePage,LPCWSTR lpcwszSrcStr) { char* lpszDesStrNULL; int lenWideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,NULL,0,NULL,NULL); lpszDesStrnew char[len1]; memset(lpszDesStr,0,sizeof(char)*(len1)); if(!lpszDesStr) return NULL; lenWideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,lpszDesStr,len,NULL,NULL); if(len) return lpszDesStr; else { delete[] lpszDesStr; return NULL; } } //Unicode 和Unicode big endian之间字节序的转换 void Coder::UnicodeEndianConvert(LPWSTR lpwszstr) { wchar_t wchtemp[2]; long index; int lenwcslen(lpwszstr); if(!len) return; //交换高低字节 直到遇到结束符 index0; while( indexlen) { wchtemp[0]lpwszstr[index]; wchtemp[1]lpwszstr[index1]; unsigned char high, low; high (wchtemp[0] 0xFF00) 8; low wchtemp[0] 0x00FF; wchtemp[0] ( low 8) | high; high (wchtemp[1] 0xFF00) 8; low wchtemp[1] 0x00FF; wchtemp[1] ( low 8) | high; lpwszstr[index]wchtemp[0]; lpwszstr[index1]wchtemp[1]; index2; } } //Unicode和Unicode big endian文件向多字节文件转换 BOOL Coder::UnicodeFileToMBFile(CString filesourcepath, CString filesavepath,TextCode tcTo) { TextCode curtc; CFile filesource,filesave;; char *pChDesNULL; char *pChTempNULL; wchar_t *pwChSrcNULL; DWORD filelength,readlen,len; int bufferlen,strlength; UINT CodePage; curtcGetCodeType(filesourcepath); //文件转换类型错误 则转换失败 if(curtcUTF8 || tcToUTF8 || curtctcTo) return FALSE; //源文件打开失败或者源文件无内容 后者保存文件建立失败 均转换失败 if(!filesource.Open(filesourcepath,CFile::modeRead) || 0(filelengthfilesource.GetLength())) return FALSE; if( !filesave.Open(filesavepath,CFile::modeCreate|CFile::modeWrite)) return FALSE; //预分配内存 分配失败则转换失败 if(filelengthPREDEFINEDSIZE) bufferlenfilelength; else bufferlenPREDEFINEDSIZE; pwChSrcnew wchar_t[(bufferlen/2)1]; if(!pwChSrc) return FALSE; //预先决定代码页 switch(tcTo) { case GB2312: CodePageCP_GB2312; break; case GBK: CodePageCP_GB2312;//特殊处理 break; case BIG5: CodePageCP_GB2312;//特殊处理 break; case UTF8: CodePageCP_UTF8; break; default: break; } filesource.Seek(sizeof(wchar_t),CFile::begin); while(filelength0) { memset(pwChSrc,0,sizeof(wchar_t)*((bufferlen/2)1)); if(filelengthPREDEFINEDSIZE) lenPREDEFINEDSIZE; else lenfilelength; readlenfilesource.Read(pwChSrc,len); if(!readlen) break; if(UNICODEBIGENDIANcurtc) UnicodeEndianConvert(pwChSrc); pChDesWCharToMByte(CodePage,pwChSrc); //GBK无法直接转换 BIG5直接转换会产生错误 二者均先转到GB2312然后再转到目的类型 if(GBKtcTo) { pChTemppChDes; pChDesGB2312ToGBK(pChDes); } if(BIG5tcTo) { pChTemppChDes; pChDesGB2312ToBIG5(pChDes); } if(pChDes) { strlengthstrlen(pChDes); filesave.Write(pChDes,strlength); filesave.Flush(); filelength-readlen; } else break; } delete[] pChDes; delete[] pChTemp; delete[] pwChSrc; return TRUE; } //多字节文件转为多字节文件 //多字节转为多字节时一般先转为UNICODE类型再转换到指定目的类型实行两次转换 BOOL Coder::MBFileToMBFile(CString filesourcepath, CString filesavepath,TextCode tcTo,TextCode tcCur) { BOOL bretFALSE; TextCode curtc; CFile filesource,filesave; char *pChDesNULL; char *pChSrcNULL; DWORD filelength,readlen,len; int bufferlen,strlength; UINT CodePageCur,CodePageTo; //由于存在误差 允许用户自定义转换 if(DefaultCodeType!tcCur) curtctcCur; else curtcGetCodeType(filesourcepath); //转换类型错误 则返回转换失败 if(curtcUTF8 || tcToUTF8 || curtctcTo) return FALSE; //源文件打开失败或者源文件无内容 后者保存文件建立失败 均返回转换失败 if(!filesource.Open(filesourcepath,CFile::modeRead) || 0(filelengthfilesource.GetLength())) return FALSE; if( !filesave.Open(filesavepath,CFile::modeCreate|CFile::modeWrite)) return FALSE; //预分配内存 分配失败则转换失败 if(filelengthPREDEFINEDSIZE) bufferlenfilelength; else bufferlenPREDEFINEDSIZE; pChSrcnew char[bufferlen1]; if(!pChSrc) return FALSE; if(UTF8curtc) filesource.Seek(3*sizeof(byte),CFile::begin); CodePageCurGetCodePage(curtc); CodePageToGetCodePage(tcTo); while(filelength0) { memset(pChSrc,0,sizeof(char)*(bufferlen1)); if(filelengthPREDEFINEDSIZE) lenPREDEFINEDSIZE; else lenfilelength; readlenfilesource.Read(pChSrc,len); if(!readlen) break; pChDesMByteToMByte(CodePageCur,CodePageTo,pChSrc); if(pChDes) { strlengthstrlen(pChDes); filesave.Write(pChDes,strlength); filelength-readlen; } else break; } delete[] pChSrc; delete[] pChDes; return TRUE; } //Unicode 和Unicode big endian文件之间转换 BOOL Coder::UnicodeEndianFileConvert(CString filesourcepath, CString filesavepath,TextCode tcTo) { TextCode curtcGetCodeType(filesourcepath); if(curtc!UNICODE curtc!UNICODEBIGENDIAN) return FALSE; if(curtctcTo) return FALSE; CFile filesource,filesave;; wchar_t *pwChDes; DWORD length; if(!filesource.Open(filesourcepath,CFile::modeRead) || !filesave.Open(filesavepath,CFile::modeCreate|CFile::modeWrite)) return FALSE; lengthfilesource.GetLength(); if(!length) return FALSE; pwChDesnew wchar_t[(length/2)1]; if(!pwChDes) return FALSE; memset(pwChDes,0,sizeof(wchar_t)*((length/2)1)); filesource.Read(pwChDes,length); UnicodeEndianConvert(pwChDes); lengthwcslen(pwChDes)*2; if(UNICODEtcTo) filesave.Write(UNICODEBOM,2*sizeof(byte)); else filesave.Write(UNICODEBEBOM,2*sizeof(byte)); filesave.Write(pwChDes,length); filesave.Flush(); delete[] pwChDes; return TRUE; } //文件转到另一种文件 //6种格式文件两两转换 共计30种转换 BOOL Coder::FileToOtherFile(CString filesourcepath, CString filesavepath, TextCode tcTo,TextCode tcCur) { TextCode curtc; BOOL bretFALSE; if(DefaultCodeType!tcCur) curtctcCur; else curtcGetCodeType(filesourcepath); if(curtctcTo) return FALSE; //UNICODE和UNICODE big endian文件之间转换 共2种 if(curtcUNICODE tcToUNICODE) bretUnicodeEndianFileConvert(filesourcepath,filesavepath,tcTo); else //多字节文件向 UNICODE和UNICODE big endian文件之间转换 共8种 if(curtcUNICODE tcToUNICODE) bretMBFileToUnicodeFile(filesourcepath,filesavepath,tcTo,curtc); else //UNICODE和UNICODE big endian文件向多字节文件转换 共8种 if(curtcUNICODE tcToUNICODE) bretUnicodeFileToMBFile(filesourcepath,filesavepath,tcTo); else //多字节文件之间转换 共12种 if(curtcUNICODE tcToUNICODE) bretMBFileToMBFile(filesourcepath,filesavepath,tcTo,curtc); return bret; } //编码类型转换为字符串 CString Coder::CodeTypeToString(TextCode tc) { CString strtype; switch(tc) { case GB2312: strtype_T(GB2312); break; case BIG5: strtype_T(Big5); break; case GBK: strtype_T(GBK); break; case UTF8: strtype_T(UTF-8); break; case UNICODE: strtype_T(Unicode); break; case UNICODEBIGENDIAN: strtype_T(Unicode big endian); break; } return strtype; } //多字节向多字节转换 char* Coder::MByteToMByte(UINT CodePageCur, UINT CodePageTo, const char* szSrcStr) { char *pchDesNULL; char *pchTempNULL; wchar_t *pwchtempNULL; //三种中文编码之间转换 if(CodePageCur!CP_UTF8 CodePageTo!CP_UTF8) { switch(CodePageCur) { case CP_GB2312: { if(CP_BIG5CodePageTo) pchDesGB2312ToBIG5(szSrcStr); else pchDesGB2312ToGBK(szSrcStr); break; } case CP_BIG5: { if(CP_GB2312CodePageTo) pchDesBIG5ToGB2312(szSrcStr); else pchDesBIG5ToGBK(szSrcStr); break; } case CP_GBK: { if(CP_GB2312CodePageTo) pchDesGBKToGB2312(szSrcStr); else pchDesGBKToBIG5(szSrcStr); break; } } } else { //从UTF-8转到其他多字节 直接转到GB2312 其他形式用GB2312做中间形式 if(CP_UTF8CodePageCur) { pwchtempMByteToWChar(CodePageCur,szSrcStr); if(CP_GB2312CodePageTo) { pchDesWCharToMByte(CP_GB2312,pwchtemp); } else { pchTempWCharToMByte(CP_GB2312,pwchtemp); if(CP_GBKCodePageTo) pchDesGB2312ToGBK(pchTemp); else pchDesGB2312ToBIG5(pchTemp); } } //从其他多字节转到UTF-8 else { if(CP_GBKCodePageCur) { pchTempGBKToGB2312(szSrcStr); pwchtempMByteToWChar(CP_GB2312,pchTemp); } else pwchtempMByteToWChar(CodePageCur,szSrcStr); pchDesWCharToMByte(CodePageTo,pwchtemp); } } delete[] pchTemp; delete[] pwchtemp; return pchDes; } //获取编码类型对应的代码页 UINT Coder::GetCodePage(TextCode tccur) { UINT CodePage; switch(tccur) { case GB2312: CodePageCP_GB2312; break; case BIG5: CodePageCP_BIG5; break; case GBK: CodePageCP_GBK; break; case UTF8: CodePageCP_UTF8; break; case UNICODEBIGENDIAN: case UNICODE: break; } return CodePage; } //指定转换时默认一次转换字节大小 void Coder::SetDefaultConvertSize(UINT nCount) { if(nCount!0) PREDEFINEDSIZEnCount; } 3.运行效果
在win7 VC 6.0下测试六种编码的转换测试通过30个方向的转换如下图所示:测试程序运行效果如下图所示:
GB2312转换到GBK编码效果如下图所示:
UTF-8转换到Big5编码的效果如下图所示:
本文代码及转码程序下载 http://download.csdn.net/user/ziyuanxiazai123
4.尚未解决的问题
(1)LCMapString函数的理解还不完全熟悉其中参数偏多理解需要一定基础知识。
(2)为什么记事本程序的转码后存在些乱码,乱码是正确的吗?因为我的程序使用了中间过渡形式因此没有任何乱码。
(3)是否有更简单和清晰的方式实现编码转换待进一步研究。