关于解决乱码问题的一点探索之一(涉及utf

您所在的位置:网站首页 bom的中文 关于解决乱码问题的一点探索之一(涉及utf

关于解决乱码问题的一点探索之一(涉及utf

2023-09-16 01:20| 来源: 网络整理| 查看: 265

在使用Visual Studio 2005进行MFC开发的时候,发现自动添加的注释变成了乱码。像这样:

// TODO: ÔÚ´ËÌí¼ÓרÓôúÂëºÍ/»òµ÷ÓûùÀà 还有这样: // TODO: ÔÚ´ËÌí¼ÓÏûÏ¢´¦Àí³ÌÐò´úÂëºÍ/»òµ÷ÓÃĬÈÏÖµ

它们正确的显示应该是

// TODO: 在此添加专用代码和/或调用基类    和 // TODO: 在此添加消息处理程序代码和/或调用默认值

当保存的时候,还出现了这样的对话框:

image

网上找了各种教程,包括什么设置“自动识别不带签名的utf-8”什么的,都没有用。所以考虑自己解决。下面是我的探索过程:

一,保存文件     首先,将文件以“Unicode(UTF-8带签名) 代码页:65001”的形式进行保存(带签名的UTF-8是指有BOM的UTF-8,至于带BOM和不带BOM的UTF-8有什么区别,请戳此)。如下图:

image

 

二,查看文件的16进制代码(就是查看文件实际上保存成什么数据了)

    使用WinHex软件打开刚刚保存的文件(当然,使用UltraEdit也可以),查看文件的16进制代码。我们找到乱码的地方,把它的16进制代码找出来,如下:

image

    为了更清楚地演示,我将乱码单独拷出来,一定要注意将文本保存成UTF-8(最好带BOM,如果使用Windows自带的文本编辑器编辑就自带BOM)保存成这样:

image

 

    文件对应的16进制代码为:

image

    最前面的三个字节“EF BB BF”就是前面所述的BOM标记,从第四个字节开始,就是文件的实际内容。观察后发现,在实际内容部分,奇数位上不是C2就是C3,偶数位的没有规律,同时,我们找出原话“在此添加专用代码和/或调用基类”对应的GBK编码值,进行比较。

表一:乱码文件中的16进制数据:

0xc3 0x94 0xc3 0x9a 0xc2 0xb4 0xc3 0x8b 0xc3 0x8c 0xc3 0xad 0xc2 0xbc 0xc3 0x93 0xc3 0x97 0xc2 0xa8 0xc3 0x93 0xc3 0x83 0xc2 0xb4 0xc3 0xba 0xc3 0x82 0xc3 0xab 0xc2 0xba 0xc3 0x8d 0x2f 0xc2 0xbb 0xc3 0xb2 0xc2 0xb5 0xc3 0xb7 0xc3 0x93 0xc3 0x83 0xc2 0xbb 0xc3 0xb9 0xc3 0x80 0xc3 0xa0

表二:“在此添加专用代码和/或调用基类”对应的GBK编码值,每个字符(汉字或者/)对应一行:

0xd4 0xda 0xb4 0xcb 0xcc 0xed 0xbc 0xd3 0xd7 0xa8 0xd3 0xc3 0xb4 0xfa 0xc2 0xeb 0xba 0xcd 0x2f 0xbb 0xf2 0xb5 0xf7 0xd3 0xc3 0xbb 0xf9 0xc0 0xe0 4,分析

     仔细观察上面的两个表中的数据,我们不难发现以下规律:

    1,将表一每行中奇数位置(除了’/’那行)的C2、C3的值去掉,剩下的值和表二中的数据高度相似。

    2,除了’/’那行,表一每行中奇数位置为C2的,后面的偶数位数字就和表二中对应位(表一种第二列对应表二第一列,表一第四列对应表二中第二列)相同,表一每行中奇数位为C3的,后面的偶数位数字加上16进制数0x40后也与表二中对应位相同(对应法则同前)。

    3,由于乱码文件是以utf-8存储的,但是经过转换后得到的编码为GBK,我们大致可以知道,出现乱码的原因就是visual studio 2005将两种编码搞混了,这应该算是一个bug吧。。毕竟visual studio 2013就从来没有碰到过。。

5,解决问题

     根据上面的规律,我们使用二进制方式读取utf-8格式编码的文件数据后经转化然后输出到GBK编码的文件中即可修正问题了。

    按照以上的规律编写一段简单的C语言程序:

#include #include int main(int argc, char const *argv[]) { FILE* fp; FILE* fp2; //打开存储乱码的文件,utf-8格式,二进制打开 if((fp2=fopen("BadCode.txt","rb+"))==NULL) { printf("Open Source File Failed!\n"); system("pause"); exit(1); } //打开、新建存储处理后数据的文件 if((fp=fopen("BadCodeH.txt","w+"))==NULL) { printf("Open/Create Destination File Failed!\n"); system("pause"); exit(1); } //纪录奇数位(高位)的数据 unsigned ch; //纪录偶数位(低位)的数据 unsigned cl; //获得数据 ch=fgetc(fp2); //判断文件的格式,utf-8或者Unicode,并跳过BOM字符 if(ch==0xef) { fgetc(fp2); fgetc(fp2); ch=fgetc(fp2); } else if(ch==0xff) { fgetc(fp2); ch=fgetc(fp2); } //不达结尾 while(!feof(fp2)) { //ASCII字符,正常输出 if(ch='A'?data-'A'+10:data-'0'; gbk=gbk*16+data; } //跳过tab键 fgetc(fp); //获得第二列utf-8的编码值 for (int i = 0; i < 6; ++i) { data=fgetc(fp); data=data>='A'?data-'A'+10:data-'0'; utf=utf*16+data; } if (id>6350) { printf("%d\t%ld\n",gbk,utf ); } mapValue2[utf-14989440]=gbk; fgetc(fp); // fgetc(fp); //重置数据 gbk=0; utf=0; id++; } fclose(fp); return true; } int main(int argc, char const *argv[]) { FILE* fp; FILE* fp2; //打开存储乱码的文件,utf-8格式,二进制打开 if((fp2=fopen("BadCode.txt","rb+"))==NULL) { printf("Open Source File Failed!\n"); system("pause"); exit(1); } //打开、新建存储处理后数据的文件 if((fp=fopen("BadCodeH.txt","w+"))==NULL) { printf("Open/Create Destination File Failed!\n"); system("pause"); exit(1); } unsigned mapValue2[330000]; if(!ReadTable(mapValue2))  {  

     printf("Convert Failed!\n");       system("pause");      exit(1);   }

//纪录奇数位(高位)的数据 unsigned ch; //纪录偶数位(低位)以及utf-8高位的数据 unsigned cl; //记录utf-8末位字节的信息 unsigned cu; ////记录正常字符的utf-8编码 unsigned long utf; //记录正常字符的gbk编码 unsigned cgbk; //获得数据 ch=fgetc(fp2); //判断文件的格式,utf-8或者Unicode,并跳过BOM字符 if(ch==0xef) { fgetc(fp2); fgetc(fp2); ch=fgetc(fp2); } else if(ch==0xff) { fgetc(fp2); ch=fgetc(fp2); } //不达结尾 while(!feof(fp2)) { //ASCII字符,正常输出 if(ch


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3