mfc 中文乱码转换为正常中文_中文编码转换

中文编码转换——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 lpcwsStrDes=NULL;

int   len=MultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,NULL,0);

lpcwsStrDes=new wchar_t[len+1];

if(!lpcwsStrDes)

return NULL;

memset(lpcwsStrDes,0,sizeof(wchar_t)*(len+1));

len=MultiByteToWideChar(CodePage,0,lpcszSrcStr,-1,lpcwsStrDes,len);

if(len)

return lpcwsStrDes;

else

{

delete[] lpcwsStrDes;

return NULL;

}

}

char* Coder::WCharToMByte(UINT CodePage,LPCWSTR lpcwszSrcStr)

{

char* lpszDesStr=NULL;

int len=WideCharToMultiByte(CodePage,0,lpcwszSrcStr,-1,NULL,0,NULL,NULL);

lpszDesStr=new char[len+1];

memset(lpszDesStr,0,sizeof(char)*(len+1));

if(!lpszDesStr)

return NULL;

len=WideCharToMultiByte(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* pBuffer=new char[nLength+1];

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_GB2312=936,

CP_BIG5=950,

CP_GBK=0         //此处特殊处理 CP_GBK仅作一标志  GBK代码页值尚未查得

}CodePages;

//txt文件编码

typedef enum TextCodeType

{

GB2312=0,

BIG5=1,

GBK=2,

UTF8=3,

UNICODE=4,

UNICODEBIGENDIAN=5,

DefaultCodeType=-1

}TextCode;

class Coder

{

public:

Coder();

virtual ~Coder();

public:

//默认一次转换字节大小

UINT  PREDEFINEDSIZE;

//指定转换时默认一次转换字节大小

void SetDefaultConvertSize(UINT nCount);

//编码类型转换为字符串

CString  CodeTypeToString(TextCode tc);

//文件转到另一种

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值