不同字符集转换为unicode和显示当前系统支持的代码页

 

不同字符集转换为unicode和显示当前系统支持的代码页  

2008-01-20 00:52:30|  分类: 默认分类 |  标签: |字号 订阅

【原创】

在写一个可以将不同字符集的字符串转换为unicode的函数,(为什么会有不同字符集的字符串?从网上抓下来的网页字符集千奇百怪,按"rb"读进来的时候就产生了不同字符集的字符串,呵呵)查了些资料,总算有些眉目。什么是mbstr什么是unicode我也不解释了,主要是写给自己看,怕忘了。具体实现不外乎两种:

1、利用windows API函数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  );
具体我就不解释了,自己看msdn好了,关键是第一个参数 unsigned int codepage,这个指定了转换时所用的代码页,是必须正确设置的。
下面给一个例程:
// we want to convert an MBCS string in lpszA  int nLen = MultiByteToWideChar(CP_ACP, 0,lpszA, -1, NULL, NULL);  LPWSTR lpszW = new WCHAR[nLen];  MultiByteToWideChar(CP_ACP, 0,   lpszA, -1, lpszW, nLen);  // use it to call OLE here  pI->SomeFunctionThatNeedsUnicode(lpszW);  // free the string  delete[] lpszW;  
这个例子中的CP_ACP是个常量,代表ANSI code page
这个例程还可以改进,你可以看到这里调用了两次MultiByteToWideChar,第一次是估计长度的,其实没有必要,一
个多字节字符对应顶多一个宽字符,所以我们简单的把多字节字符长度*2就好了,虽然会有些浪费,但效率有所提
高,或者还有一个做法,用c函数_mbstrlen()来获得准确字符个数,这个待会儿说
 
上面这个例程有些偏长,如果你频繁需要在多字节字符串和unicode之间转换的话,还可以利用ATL的转换宏
A2CW        (LPCSTR) -> (LPCWSTR)  A2W        (LPCSTR) -> (LPWSTR)  W2CA        (LPCWSTR) -> (LPCSTR)  W2A        (LPCWSTR) -> (LPSTR)
注意要包含AFXPRIV.H,并声明USES_CONVERSION;  具体解释和优点我前一篇日志里有
但是这个宏不方便的地方在于无法指定代码页,那就只能在当前代码页字符串和unicode之间转换了
 
2、利用C函数mbstowcs
函数原型:
size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count );
具体解释自己参看msdn
 
注意到这里没有让你设置代码页的参数,怎么办?
你需要调用另一个函数setlocal,原型如下:
 
char *setlocale( int category, const char *locale );
其中,第一个参数是你所设置的locale影响的类别,大概有时间啊货币啊字符啊什么的,嫌麻烦的话赋值为LC_ALL好了,后一个参数指名了代码页,具体是这样的
locale :: "lang[_country[.code_page]]"               | ".code_page"              | ""              | NULL  可以设置 lang country 或者code_page,对于我们所关心的不同字符集而言,code_page是我们要设置的,那这个code_page该怎么设置呢?怎么样获得当前的代码页和系统支持的代码页,找了写资料,windowsAPI提供了这样的函数,下面是例程:
#include <windows.h>
#include <stdio.h>
UINT CALLBACK EnumCodePagesProc(char *lpCodePagesString)
{
 printf("支持:%s 代码页\n",lpCodePagesString);
 return true;
}
void main()
{
 printf("当前代码页为:%d\n",GetACP());
 EnumSystemCodePages(&EnumCodePagesProc,CP_SUPPORTED);
 
}
具体不解释了,自己参考msdn
//一段小插曲:msdn上说EnumCodePagesProc这个回调函数应该是bool型的,结果一编译出错,应该是UINT型的,呵
 
但是这样获得的都是一些整数值,怎么知道具体对应那些编码呢,嘿嘿,这个对应表也让我找到了,po出来

     
     

37

IBM037

IBM EBCDIC(美国 - 加拿大)

437

IBM437

OEM 美国

500

IBM500

IBM EBCDIC(国际)

708

ASMO-708

阿拉伯字符 (ASMO 708)

720

DOS-720

阿拉伯字符 (DOS)

737

ibm737

希腊字符 (DOS)

775

ibm775

波罗的海字符 (DOS)

850

ibm850

西欧字符 (DOS)

852

ibm852

中欧字符 (DOS)

855

IBM855

OEM 西里尔语

857

ibm857

土耳其字符 (DOS)

858

IBM00858

OEM 多语言拉丁语 I

860

IBM860

葡萄牙语 (DOS)

861

ibm861

冰岛语 (DOS)

862

DOS-862

希伯来字符 (DOS)

863

IBM863

加拿大法语 (DOS)

864

IBM864

阿拉伯字符 (864)

865

IBM865

北欧字符 (DOS)

866

cp866

西里尔字符 (DOS)

869

ibm869

现代希腊字符 (DOS)

870

IBM870

IBM EBCDIC(多语言拉丁语 2)

874

windows-874

泰语 (Windows)

875

cp875

IBM EBCDIC(现代希腊语)

932

shift_jis

日语 (Shift-JIS)

936

gb2312

简体中文 (GB2312)

*

949

ks_c_5601-1987

朝鲜语

950

big5

繁体中文 (Big5)

1026

IBM1026

IBM EBCDIC(土耳其拉丁语 5)

1047

IBM01047

IBM 拉丁语 1

1140

IBM01140

IBM EBCDIC(美国 - 加拿大 - 欧洲)

1141

IBM01141

IBM EBCDIC(德国 - 欧洲)

1142

IBM01142

IBM EBCDIC(丹麦 - 挪威 - 欧洲)

1143

IBM01143

IBM EBCDIC(芬兰 - 瑞典 - 欧洲)

1144

IBM01144

IBM EBCDIC(意大利 - 欧洲)

1145

IBM01145

IBM EBCDIC(西班牙 - 欧洲)

1146

IBM01146

IBM EBCDIC(英国 - 欧洲)

1147

IBM01147

IBM EBCDIC(法国 - 欧洲)

1148

IBM01148

IBM EBCDIC(国际 - 欧洲)

1149

IBM01149

IBM EBCDIC(冰岛语 - 欧洲)

1200

utf-16

Unicode

*

1201

UnicodeFFFE

Unicode (Big-Endian)

*

1250

windows-1250

中欧字符 (Windows)

1251

windows-1251

西里尔字符 (Windows)

1252

Windows-1252

西欧字符 (Windows)

*

1253

windows-1253

希腊字符 (Windows)

1254

windows-1254

土耳其字符 (Windows)

1255

windows-1255

希伯来字符 (Windows)

1256

windows-1256

阿拉伯字符 (Windows)

1257

windows-1257

波罗的海字符 (Windows)

1258

windows-1258

越南字符 (Windows)

1361

Johab

朝鲜语 (Johab)

10000

macintosh

西欧字符 (Mac)

10001

x-mac-japanese

日语 (Mac)

10002

x-mac-chinesetrad

繁体中文 (Mac)

10003

x-mac-korean

朝鲜语 (Mac)

*

10004

x-mac-arabic

阿拉伯字符 (Mac)

10005

x-mac-hebrew

希伯来字符 (Mac)

10006

x-mac-greek

希腊字符 (Mac)

10007

x-mac-cyrillic

西里尔字符 (Mac)

10008

x-mac-chinesesimp

简体中文 (Mac)

*

10010

x-mac-romanian

罗马尼亚语 (Mac)

10017

x-mac-ukrainian

乌克兰语 (Mac)

10021

x-mac-thai

泰语 (Mac)

10029

x-mac-ce

中欧字符 (Mac)

10079

x-mac-icelandic

冰岛语 (Mac)

10081

x-mac-turkish

土耳其字符 (Mac)

10082

x-mac-croatian

克罗地亚语 (Mac)

20000

x-Chinese-CNS

繁体中文 (CNS)

20001

x-cp20001

TCA 台湾

20002

x-Chinese-Eten

繁体中文 (Eten)

20003

x-cp20003

IBM5550 台湾

20004

x-cp20004

TeleText 台湾

20005

x-cp20005

Wang 台湾

20105

x-IA5

西欧字符 (IA5)

20106

x-IA5-German

德语 (IA5)

20107

x-IA5-Swedish

瑞典语 (IA5)

20108

x-IA5-Norwegian

挪威语 (IA5)

20127

us-ascii

US-ASCII

*

20261

x-cp20261

T.61

20269

x-cp20269

ISO-6937

20273

IBM273

IBM EBCDIC(德国)

20277

IBM277

IBM EBCDIC(丹麦 - 挪威)

20278

IBM278

IBM EBCDIC(芬兰 - 瑞典)

20280

IBM280

IBM EBCDIC(意大利)

20284

IBM284

IBM EBCDIC(西班牙)

20285

IBM285

IBM EBCDIC(英国)

20290

IBM290

IBM EBCDIC(日语片假名)

20297

IBM297

IBM EBCDIC(法国)

20420

IBM420

IBM EBCDIC(阿拉伯语)

20423

IBM423

IBM EBCDIC(希腊语)

20424

IBM424

IBM EBCDIC(希伯来语)

20833

x-EBCDIC-KoreanExtended

IBM EBCDIC(朝鲜语扩展)

20838

IBM-Thai

IBM EBCDIC(泰语)

20866

koi8-r

西里尔字符 (KOI8-R)

20871

IBM871

IBM EBCDIC(冰岛语)

20880

IBM880

IBM EBCDIC(西里尔俄语)

20905

IBM905

IBM EBCDIC(土耳其语)

20924

IBM00924

IBM 拉丁语 1

20932

EUC-JP

日语(JIS 0208-1990 和 0212-1990)

20936

x-cp20936

简体中文 (GB2312-80)

*

20949

x-cp20949

朝鲜语 Wansung

*

21025

cp1025

IBM EBCDIC(西里尔塞尔维亚 - 保加利亚语)

21866

koi8-u

西里尔字符 (KOI8-U)

28591

iso-8859-1

西欧字符 (ISO)

*

28592

iso-8859-2

中欧字符 (ISO)

28593

iso-8859-3

拉丁语 3 (ISO)

28594

iso-8859-4

波罗的海字符 (ISO)

28595

iso-8859-5

西里尔字符 (ISO)

28596

iso-8859-6

阿拉伯字符 (ISO)

28597

iso-8859-7

希腊字符 (ISO)

28598

iso-8859-8

希伯来字符 (ISO-Visual)

*

28599

iso-8859-9

土耳其字符 (ISO)

28603

iso-8859-13

爱沙尼亚语 (ISO)

28605

iso-8859-15

拉丁语 9 (ISO)

29001

x-Europa

欧罗巴

38598

iso-8859-8-i

希伯来字符 (ISO-Logical)

*

50220

iso-2022-jp

日语 (JIS)

*

50221

csISO2022JP

日语(JIS- 允许 1 字节假名)

*

50222

iso-2022-jp

日语(JIS- 允许 1 字节假名 - SO/SI)

*

50225

iso-2022-kr

朝鲜语 (ISO)

*

50227

x-cp50227

简体中文 (ISO-2022)

*

51932

euc-jp

日语 (EUC)

*

51936

EUC-CN

简体中文 (EUC)

*

51949

euc-kr

朝鲜语 (EUC)

*

52936

hz-gb-2312

简体中文 (HZ)

*

54936

GB18030

简体中文 (GB18030)

*

57002

x-iscii-de

ISCII 梵文

*

57003

x-iscii-be

ISCII 孟加拉语

*

57004

x-iscii-ta

ISCII 泰米尔语

*

57005

x-iscii-te

ISCII 泰卢固语

*

57006

x-iscii-as

ISCII 阿萨姆语

*

57007

x-iscii-or

ISCII 奥里雅语

*

57008

x-iscii-ka

ISCII 卡纳达语

*

57009

x-iscii-ma

ISCII 马拉雅拉姆语

*

57010

x-iscii-gu

ISCII 古吉拉特语

*

57011

x-iscii-pa

ISCII 旁遮普语

*

65000

utf-7

Unicode (UTF-7)

*

65001

utf-8

Unicode (UTF-8)

*

65005

utf-32

Unicode (UTF-32)

*

65006

utf-32BE

Unicode (UTF-32 Big-Endian)

*

看到了吧,我们的汉语是936,utf_8是65001,这下你可以把这个整数值写到setlocale中,然后调用mbswcs就可以了。
给个GB编码文件的例程:
FILE *in=fopen(fname, "rb");
long length=_filelength(_fileno(in));
//包含在io.h中,获得文件的字符数
setlocale(LC_ALL, ".936"); 
char *MbText=new char[length+1];
//动态分配内存,长度为(length+1)*sizeof(char)
fread(MbText, sizeof(char), length, in);
MbText[length]='\0';
NumOfChar=_mbstrlen(MbText);
RawText=new wchar_t[NumOfChar+1];
mbstowcs(RawText, MbText, length)
RawText[NumOfChar]=L'\0';
delete []MbText;
 
哈哈,问题解决。
 
哦,还有个如何获取字符串长度的问题,
上面说过用_mbstrlen(),它会根据你设置的代码页进行字符验证,
得出准确的字符串长度,也就是字符个数
 
不同字符集转换为unicode问题基本解决,反方向呢?那自然有反方向的函数,道理一样,自己到msdn上看吧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值