转:http://blog.csdn.net/exbob/article/details/6542564
对于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。程序如下:
//由unicode.txt和gbk.txt生成uni2gbk.txt
#include <stdio.h>
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)
{
//读取unicode编码,写入uni2gbk.txt
buffer[0]=fgetc(fup);
buffer[1]=fgetc(fup);
fputc(buffer[0],fwp);
fputc(buffer[1],fwp);
//读取gbk编码,写入uni2gbk.txt
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排序
//由unicode.txt和gbk.txt生成uni2gbk.txt
#include <stdio.h>
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)
{
//读取unicode编码,写入uni2gbk.txt
buffer[0]=fgetc(fup);
buffer[1]=fgetc(fup);
fputc(buffer[0],fwp);
fputc(buffer[1],fwp);
//读取gbk编码,写入uni2gbk.txt
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 <stdio.h>
#include <stdlib.h>
#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<MAXSIZE && flag==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 <stdio.h>
#include <stdlib.h>
union code
{
unsigned int unigbk;
unsigned short int uni_gbk[2];
unsigned char buffer[4];
};
int main()
{
unsigned short int count=0x00A4; //从unicode的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); //舍弃uni2gbkp.txt文件的前0x80EC个字节
fread(temp.buffer,1,4,frp);
while(count<=0xffe5) //以unicode的0xffe5结束
{
if(temp.uni_gbk[0]==count) //判断unicode编码是否连续
{
fputc(temp.buffer[2],fwp); //将对应的gbk编码写入uni2gbk.bin
fputc(temp.buffer[3],fwp);
fread(temp.buffer,1,4,frp);
}
else //不连续的地方填充0
{
fputc(0x00,fwp);
fputc(0x00,fwp);
}
count++;
}
fclose(frp);
fclose(fwp);
return 0;
}
下载:
unicode点阵字库文件:http://download.csdn.net/source/3362591