|
4.1.3 文件编码为UTF-8
对于UTF-8而言,UTF-8的编码其实不属于宽字符,它还是MBCS。wcout函数只能显示宽字符,不能够正确显示它的编码,所以输出为乱码或空。
4.2 编码转换后显示
4.2.1 文件编码为UNICODE Big Endian
由于字节序的问题,需要转换成Little Endian 才能正确显示,因为x86系列用的是Little Endian。转换后,请用下面小节的方法显示。
4.2.2 文件编码为UNICODE Little Endian
读文件程序如下:
FILE *myfile;
wchar_t *name=L"CharsetExample.txt";
myfile=_wfopen(name,L"rb");
fseek(myfile,0,0);
wchar_t buffw[100];
fgetws(buffw,100,myfile);
printf("字节数=%d\n",wcslen(buffw));
printf("16进制值=");
for(int i=0;i<wcslen(buffw);i++)
printf("%hhx\t",buffw[i]);
//宽字符转换成多字节,第一个参数是Code Page,windows定义了若干Code Page,用来处理不同语言编码的。CP_ACP是ASCII编码,这里主要是求出转换后的字节数。Buffw+1主要是去掉头标记feff。
UNICODEàASCII编码
int len = WideCharToMultiByte( CP_ACP, 0, buffw+1, wcslen(buffw+1), NULL, NULL, NULL, NULL );
LPSTR lpsz = new CHAR[len+1];
//下面才是真正的转换。
WideCharToMultiByte( CP_ACP, 0, buffw+1, wcslen(buffw+1), lpsz, len, NULL,NULL );
printf("%d",len);
lpsz[len]='\0';
printf("\n%s\n",lpsz);
结果如下:
字节数=12
16进制值=feff 60a8 597d 2c 59….
字符串输出=您好, Ye Ming!
转换完后,系统函数printf会按照系统默认编码显示出来。
4.2.3 文件编码为UTF-8
文件保存为UTF-8,有两种情况:
· 错误:按宽字符存取
程序如下:
FILE *myfile;
wchar_t *name=L"CharsetExample.txt";
myfile=_wfopen(name,L"rb");
fseek(myfile,3,0);
wchar_t buffw[100];
fgetws(buffw,100,myfile);
printf("字节数=%d\n",wcslen(buffw));
printf("16进制值=");
for(int i=0;i<wcslen(buffw);i++)
printf("%hhx\t",buffw[i]);
…………….
结果如下:
字节数=7
16进制值=82e6 e5a8 bda5 592c 2065 694d 676e
可以看出,16进制值缺了21,这就是感叹号的ASCII值。当以fgetws读取文件时,21落单了,所以不能读进wchar_t。
· 正确:按字节存取
程序如下:
FILE *myfile;
wchar_t *name=L"CharsetExample.txt";
myfile=_wfopen(name,L"rb");
fseek(myfile,3,0);
char buff[100];
//取得所有UTF-8字节
fgets(buff,100,myfile);
printf("字节数=%d\n",strlen(buff));
printf("16进制值=");
for(int i=0;i<strlen(buff);i++)
printf("%hhx\t",buff[i]);
第一步,UTF-8àUNICODE
由于从UTF-8不能直接转换为ASCII编码,必须以UNICODE为跳板;这里用到参数CP_UTF8,因为我们是将UTF-8转换为UNICODE,注意:WideChar在本函数中指的肯定是UNICODE。
int num=MultiByteToWideChar(CP_UTF8,NULL,buff,-1,NULL,NULL);
wchar_t *buffw2=new wchar_t[num];
MultiByteToWideChar(CP_UTF8,NULL,buff,-1,buffw2,num);
第二步,UNICODEàASCII编码
这个函数跟之前用过了。
int len = WideCharToMultiByte( CP_ACP, 0, buffw2, num, NULL, NULL, NULL, NULL );
LPSTR lpsz = new CHAR[len+1];
WideCharToMultiByte( CP_ACP, 0, buffw2, num, lpsz, len, NULL, NULL );
lpsz[len]='\0';
printf("\n字符串输出=");
printf("%s\n",lpsz);
结果如下:
字节数=15
16进制值=e6 82 a8 e5 a5 bd 2c 59 65 20 4d 69 6e 67 21
字符串输出=您好, Ye Ming!
结果正确,*_*。
4.3 转换编码的另外一种方法
· mbstowcs
char *ccname="我们";
wchar_t * wwname=new wchar_t[2];
//依赖于Locale而不是Code Page
setlocale(LC_CTYPE,"chs");
mbstowcs(wwname,ccname,2);
wcout<<wwname<<endl;
· wcstombs
wchar_t *wname=L"叶明";
char * cname=new char[4];
setlocale(LC_TIME,"chs");
wcout<<wname<<endl;
wcstombs(cname,wname,4);
printf("%s\n",cname);
5. 思考字符集编码对软件的影响
请参考本人另外一篇文章:UNICODE 编码对软件编程的影响。
6. 常用参数
· ASCII码参照表
下面是部分的Code Page:
CP0 ASCII
CP932 Shift-JIS
CP936 GBK
CP950 Big5
CP20936 GB2312
CP65001 UTF-8
CP65000 UTF-7
由于国家和本地习惯的不同,在处理文字、日期、数字、货币格式等问题都会有所不同,Locale就是用来解决这个问题。
C语言的Locale定义,分为以下几类:
LC_ALL:代表所有的locale
LC_CTYPE:用来处理文字编码
LC_MESSAGES:信息的显示,你可能会在这样一个目录看到大量的mo文件
LC_TIME:时间格式
LC_NUMERIC:数字格式
LC_MONETARY:货币格式
LC_COLLATE:字母顺序和特殊字符的比较
其中比较重要的是:
字符编码LC_CTYPE和本地化的信息显示LC_MESSAGES 。
设置Locale举例如下:
setLocale(LC_ALL, "chs")
值可取下面值:
zh_CN.utf8
chs
Chinese-simplified
ZHI
.936
----文章结束----
共3页: 上一页 [1] [2] 3 下一页
|