Chinaunix首页 | 论坛 | 博客
  • 博客访问: 869181
  • 博文数量: 189
  • 博客积分: 4310
  • 博客等级: 上校
  • 技术积分: 1925
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-27 08:56
文章分类

全部博文(189)

文章存档

2015年(1)

2013年(2)

2012年(1)

2011年(39)

2010年(98)

2009年(48)

分类: C/C++

2011-10-09 17:22:13

对于unicode编码的字符,可以先将unicode编码转换为GBK编码,然后利用GBK点阵字库(gbk.bin)显示字符。一个比较好的编码转换方法是,制作一个按照unicode编码顺序排列的GBK编码表,直接根据unicode编码就可以查到对应的GBK编码,具体的制作方法如下:

 

1.生成一个unicode字符文件

上以篇文章中已经制作了一个GBK编码的全字符文件gbk.txt,用记事本打开gbk.txt,然后以unicode编码另存为unicode.txt文件。

这样的话,所有的GBK编码字符都用unicode编码保存在unicode.txt中了,可以用winhex打开unicode.txt,会发现前两个字节是FFFE,这是unicode编码的标识,要注意后面的unicode编码是小端存储。

 

2.制作unicode转gbk的文件

这里要用程序制作一个unicode与gbk编码相对应的文件,该文件每四个字节为一组,其中前两个字节为unicode编码,后两个字节是对应的gbk编码,两种编码都以小端存储,数据结构如下:

  1. union code  
  2.   
  3. {  
  4.   
  5. unsigned int unigbk;  
  6.   
  7. unsigned short int uni_gbk[2];  
  8.   
  9. unsigned char buffer[4];  
  10.   
  11. };  

这个数据结构是以gbk编码的顺序存放在文件uni2gbk.txt中,文件大小为128764Byte。程序如下:

  1. //由unicode.txt和gbk.txt生成uni2gbk.txt  
  2. #include   
  3.   
  4. int main(void)  
  5. {  
  6.     unsigned char buffer[2];  
  7.     int count=0;  
  8.   
  9.     FILE *fup=0;  
  10.     FILE *fgp=0;  
  11.     FILE *fwp=0;  
  12.   
  13.     fup=fopen("unicode.txt","rb");  
  14.     fgp=fopen("gbk.txt","rb");  
  15.     fwp=fopen("uni2gbk.txt","wb");  
  16.   
  17.     fgetc(fup);  
  18.     fgetc(fup);  
  19.   
  20.     while(1)  
  21.     {  
  22.         //读取unicode编码,写入uni2gbk.txt  
  23.         buffer[0]=fgetc(fup);  
  24.         buffer[1]=fgetc(fup);  
  25.         fputc(buffer[0],fwp);  
  26.         fputc(buffer[1],fwp);  
  27.         //读取gbk编码,写入uni2gbk.txt  
  28.         buffer[0]=fgetc(fgp);  
  29.         buffer[1]=fgetc(fgp);  
  30.         fputc(buffer[1],fwp);  
  31.         fputc(buffer[0],fwp);  
  32.   
  33.         count+=2;  
  34.         if(count==0xfb7c)  
  35.             printf("xxxxxxxxx/n");  
  36.   
  37.   
  38.         if(buffer[0]==0xfe && buffer[1]==0xfe)  
  39.         {  
  40.             printf("count = %x/n",count);  
  41.   
  42.             fclose(fup);  
  43.             fclose(fgp);  
  44.             fclose(fwp);  
  45.   
  46.             return;  
  47.         }  
  48.     }  
  49.     return 0;  
  50. }  
 3.将uni2gbk.txt排序

用程序将uni2gbk.txt文件中的union code数据结构按照unicode编码的顺序从小到大排序,程序如下:

  1. #include   
  2. #include   
  3.  
  4. #define MAXSIZE (0x7DBF)  //union code的个数  
  5.   
  6. union code  
  7. {  
  8.     unsigned int unigbk;  
  9.     unsigned short int uni_gbk[2];  
  10.     unsigned char buffer[4];  
  11. };  
  12.   
  13.   
  14. int main(void)  
  15. {  
  16.     unsigned char flag=1;  
  17.   
  18.     unsigned int i=0;  
  19.     unsigned int j=0;  
  20.   
  21.     union code pdata;  
  22.     union code ndata;  
  23.   
  24.     FILE *fp=0;  
  25.   
  26.     fp = fopen("uni2gbk.txt","rb+");  
  27.   
  28.     for(i=1; i
  29.     {  
  30.         flag=0;  
  31.   
  32.         for(j=0; j<(MAXSIZE-i); j++)  
  33.         {  
  34.             fseek(fp,j*4,0);  
  35.             fread(pdata.buffer,1,4,fp);  
  36.             fseek(fp,j*4+4,0);  
  37.             fread(ndata.buffer,1,4,fp);  
  38.   
  39.             if(pdata.uni_gbk[0]>ndata.uni_gbk[0])  
  40.             {  
  41.                 flag=1;  
  42.   
  43.                 fseek(fp,j*4,0);  
  44.                 fwrite(ndata.buffer,4,1,fp);  
  45.                 fseek(fp,j*4+4,0);  
  46.                 fwrite(pdata.buffer,4,1,fp);  
  47.   
  48.             }  
  49.   
  50.         }  
  51.   
  52.         printf("i=%d/n",i);  
  53.     }  
  54.   
  55.     fclose(fp);  
  56.   
  57. }  

排序后,为了与没有排序的uni2gbk.txt区分,将文件名改为uni2gbkp.txt。

 

4.删除无用的编码

用winhex打开uni2gbkp.txt,可以发现,从0到第0x80EB个字节中的unicode编码都是0x0020或0x003F,这些都是无用的编码,它们所对应的gbk编码也是无用的,都可以删除。

删除后,uni2gbkp.txt文件中的union code数据结构的unicode编码就是从0x00A4开始,以0xFFE5结束。但是这些unicode编码不是连续的,例如0x00A4之后就是0x00A7,为了方便查找,需要在不连续的编码中间用union code填充,对应的gbk编码部分用0x0000填充,然后将union code中的unicode编码全部删除。最后生成uni2gbk.bin文件。程序如下:

 

  1. #include   
  2. #include   
  3.   
  4. union code  
  5. {  
  6.     unsigned int unigbk;  
  7.     unsigned short int uni_gbk[2];  
  8.     unsigned char buffer[4];  
  9. };  
  10.   
  11. int main()  
  12. {  
  13.     unsigned short int count=0x00A4;  //从unicode的0x00A4开始  
  14.     union code temp;  
  15.   
  16.     FILE *frp=0;  
  17.     FILE *fwp=0;  
  18.   
  19.     frp=fopen("uni2gbkp.txt","rb");  
  20.     fwp=fopen("uni2gbk.bin","wb");  
  21.   
  22.     fseek(frp,0x80EC,SEEK_SET);  //舍弃uni2gbkp.txt文件的前0x80EC个字节  
  23.     fread(temp.buffer,1,4,frp);  
  24.   
  25.     while(count<=0xffe5) //以unicode的0xffe5结束  
  26.     {  
  27.         if(temp.uni_gbk[0]==count)     //判断unicode编码是否连续  
  28.         {  
  29.             fputc(temp.buffer[2],fwp);  //将对应的gbk编码写入uni2gbk.bin  
  30.             fputc(temp.buffer[3],fwp);  
  31.             fread(temp.buffer,1,4,frp);  
  32.         }  
  33.         else                        //不连续的地方填充0  
  34.         {  
  35.             fputc(0x00,fwp);  
  36.             fputc(0x00,fwp);  
  37.         }  
  38.   
  39.         count++;  
  40.     }  
  41.     fclose(frp);  
  42.     fclose(fwp);  
  43.     return 0;  
  44. }  

生成的uni2gbk.bin文件中都是gbk编码,这些gbk编码都是按照对应的unicode编码(0x00A4到0xFFE5)的顺序排列的。

 

5.uni2gbk.bin的使用

假设一个字符的unicode编码为X,那么它对应的gbk编码在uni2gbk.bin文件中的位置就是:

(X-0x00A4)*2

从这个位置读取一个unsigned short int数据,就是它的gbk码。然后利用GBK点阵字库(gbk.bin)即可显示。

例如,以Linux的终端模拟点阵屏幕,程序如下:

  1. #include   
  2. #include   
  3. #include   
  4.   
  5. #define START 0x8140  
  6. #define DATANUM 0x20  
  7.   
  8. int displaychar(FILE *fp,unsigned short int dispch,char fillch,char start_x,char start_y);  
  9.   
  10. int main(void)  
  11. {  
  12.     FILE * fp=0;  
  13.     unsigned short int testch = 0x7231;  //汉字'爱‘的unicode码  
  14.     unsigned short int gbkch=0;       //存放testch的gbk编码  
  15.   
  16.     //将unicode转换为gbk  
  17.     fp = fopen("uni2gbk.bin","rb");  
  18.     fseek(fp,(testch-0x00A4)*((unsigned int)2),SEEK_SET);  
  19.   
  20.     gbkch = fgetc(fp);  
  21.     gbkch = (fgetc(fp)<<8) + gbkch;  
  22.   
  23.     fclose(fp);  
  24.   
  25.     fp = fopen("gbk.bin","rb");  
  26.   
  27.     initscr();  
  28.   
  29.     displaychar(fp,gbkch,'*',0,0);  
  30.   
  31.     refresh();  
  32.   
  33.     while(1);  
  34.     endwin();  
  35.   
  36.     fclose(fp);  
  37.     return 0;  
  38. }  
  39.   
  40. /* 
  41.  * fp指向点阵字库二进制文件 
  42.  * 以点阵方式显示一个GBK字符 
  43.  * dispch是要显示的字符,fillch是填充点阵的字符 
  44.  * start_x,start_y是显示的起始坐标 
  45.  */  
  46. int displaychar(FILE *fp,unsigned short int dispch,char fillch,char start_x,char start_y)  
  47. {  
  48.     char x=start_x;  
  49.     char y=start_y;  
  50.     unsigned int location=(dispch-START)*DATANUM;  
  51.   
  52.     int i=0;  
  53.     int j=0;  
  54.     char buf=0;  
  55.   
  56.     fseek(fp,location,SEEK_SET);  
  57.   
  58.     for(i=0;i
  59.     {  
  60.         buf=fgetc(fp);  
  61.   
  62.         //显示一个字节  
  63.         for(j=0;j<8;j++)  
  64.         {  
  65.             move(y+j,x);  
  66.             if( buf & (0x01<
  67.             {  
  68.                 addch(fillch);  
  69.             }  
  70.         }  
  71.   
  72.         if(x == (start_x+15))  
  73.         {  
  74.             x=start_x;  
  75.             y=start_y+8;  
  76.         }  
  77.         else  
  78.             x++;  
  79.     }  
  80.     return 0;  
  81.   
  82. }  

 

阅读(4781) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~