对于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编码,两种编码都以小端存储,数据结构如下:
- union code
-
- {
-
- unsigned int unigbk;
-
- unsigned short int uni_gbk[2];
-
- unsigned char buffer[4];
-
- };
这个数据结构是以gbk编码的顺序存放在文件uni2gbk.txt中,文件大小为128764Byte。程序如下:
-
- #include
-
- int main(void)
- {
- unsigned char buffer[2];
- int count=0;
-
- FILE *fup=0;
- FILE *fgp=0;
- FILE *fwp=0;
-
- fup=fopen("unicode.txt","rb");
- fgp=fopen("gbk.txt","rb");
- fwp=fopen("uni2gbk.txt","wb");
-
- fgetc(fup);
- fgetc(fup);
-
- while(1)
- {
-
- buffer[0]=fgetc(fup);
- buffer[1]=fgetc(fup);
- fputc(buffer[0],fwp);
- fputc(buffer[1],fwp);
-
- buffer[0]=fgetc(fgp);
- buffer[1]=fgetc(fgp);
- fputc(buffer[1],fwp);
- fputc(buffer[0],fwp);
-
- count+=2;
- if(count==0xfb7c)
- printf("xxxxxxxxx/n");
-
-
- if(buffer[0]==0xfe && buffer[1]==0xfe)
- {
- printf("count = %x/n",count);
-
- fclose(fup);
- fclose(fgp);
- fclose(fwp);
-
- return;
- }
- }
- return 0;
- }
3.将uni2gbk.txt排序用程序将uni2gbk.txt文件中的union code数据结构按照unicode编码的顺序从小到大排序,程序如下:
- #include
- #include
-
- #define MAXSIZE (0x7DBF) //union code的个数
-
- union code
- {
- unsigned int unigbk;
- unsigned short int uni_gbk[2];
- unsigned char buffer[4];
- };
-
-
- int main(void)
- {
- unsigned char flag=1;
-
- unsigned int i=0;
- unsigned int j=0;
-
- union code pdata;
- union code ndata;
-
- FILE *fp=0;
-
- fp = fopen("uni2gbk.txt","rb+");
-
- for(i=1; i
- {
- flag=0;
-
- for(j=0; j<(MAXSIZE-i); j++)
- {
- fseek(fp,j*4,0);
- fread(pdata.buffer,1,4,fp);
- fseek(fp,j*4+4,0);
- fread(ndata.buffer,1,4,fp);
-
- if(pdata.uni_gbk[0]>ndata.uni_gbk[0])
- {
- flag=1;
-
- fseek(fp,j*4,0);
- fwrite(ndata.buffer,4,1,fp);
- fseek(fp,j*4+4,0);
- fwrite(pdata.buffer,4,1,fp);
-
- }
-
- }
-
- printf("i=%d/n",i);
- }
-
- fclose(fp);
-
- }
排序后,为了与没有排序的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文件。程序如下:
- #include
- #include
-
- union code
- {
- unsigned int unigbk;
- unsigned short int uni_gbk[2];
- unsigned char buffer[4];
- };
-
- int main()
- {
- unsigned short int count=0x00A4;
- union code temp;
-
- FILE *frp=0;
- FILE *fwp=0;
-
- frp=fopen("uni2gbkp.txt","rb");
- fwp=fopen("uni2gbk.bin","wb");
-
- fseek(frp,0x80EC,SEEK_SET);
- fread(temp.buffer,1,4,frp);
-
- while(count<=0xffe5)
- {
- if(temp.uni_gbk[0]==count)
- {
- fputc(temp.buffer[2],fwp);
- fputc(temp.buffer[3],fwp);
- fread(temp.buffer,1,4,frp);
- }
- else
- {
- fputc(0x00,fwp);
- fputc(0x00,fwp);
- }
-
- count++;
- }
- fclose(frp);
- fclose(fwp);
- return 0;
- }
生成的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的终端模拟点阵屏幕,程序如下:
- #include
- #include
- #include
-
- #define START 0x8140
- #define DATANUM 0x20
-
- int displaychar(FILE *fp,unsigned short int dispch,char fillch,char start_x,char start_y);
-
- int main(void)
- {
- FILE * fp=0;
- unsigned short int testch = 0x7231;
- unsigned short int gbkch=0;
-
-
- fp = fopen("uni2gbk.bin","rb");
- fseek(fp,(testch-0x00A4)*((unsigned int)2),SEEK_SET);
-
- gbkch = fgetc(fp);
- gbkch = (fgetc(fp)<<8) + gbkch;
-
- fclose(fp);
-
- fp = fopen("gbk.bin","rb");
-
- initscr();
-
- displaychar(fp,gbkch,'*',0,0);
-
- refresh();
-
- while(1);
- endwin();
-
- fclose(fp);
- return 0;
- }
-
-
-
-
-
-
-
- int displaychar(FILE *fp,unsigned short int dispch,char fillch,char start_x,char start_y)
- {
- char x=start_x;
- char y=start_y;
- unsigned int location=(dispch-START)*DATANUM;
-
- int i=0;
- int j=0;
- char buf=0;
-
- fseek(fp,location,SEEK_SET);
-
- for(i=0;i
- {
- buf=fgetc(fp);
-
-
- for(j=0;j<8;j++)
- {
- move(y+j,x);
- if( buf & (0x01<
- {
- addch(fillch);
- }
- }
-
- if(x == (start_x+15))
- {
- x=start_x;
- y=start_y+8;
- }
- else
- x++;
- }
- return 0;
-
- }
阅读(4781) | 评论(0) | 转发(0) |