由UTF-8转GBK显示,思路如下:
UTF-8 转 Unicode,Unicode查表转GBK,再根据字库显示
第一步:需要了解UTF-8转UNICODE 规则
UTF-8是一种变长字节编码方式。对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。UTF-8最多可用到6个字节。
如表:
1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
因此UTF-8中可以用来表示字符编码的实际位数最多有31位,即上表中x所表示的位。
除去那些控制位(每字节开头的10等),这些x表示的位与UNICODE编码是一一对应的,位高低顺序也相同。
(这是规则的关键点)
实际将UNICODE转换为UTF-8编码时应先去除高位0,然后根据所剩编码的位数决定所需最小的UTF-8编码位数。
因此那些基本ASCII字符集中的字符(UNICODE兼容ASCII)只需要一个字节的UTF-8编码(7个二进制位)便可以表示。
如:南:(以下为十六进制)
UTF-8 E5 8D 97
1110 0101 1000 1101 1001 0111
Unicode 5 3 5 7
第二步:Unicode转GBK
通过Unicode码得到该字所在地址,在文件中读取GBK编码的字, 该查表文件
https://download.youkuaiyun.com/download/sjygqz/12505477
u16 OneUNICODEtoGBK(u16 unicode) //用二分查找算法
{
u32 offset;
u16 temp;
UINT bw;
u8 buff[2];
if(unicode<=0X9FA5)
{
if(unicode>=0X4E00)
offset=unicode-0X4E00;//0x1b87 //0X4E00,汉字偏移起点
else
return 0x2020; //不能显示的字符就给两个空格填充,否则乱码
}
else if(unicode>0X9FA5)//是标点符号
{
if(unicode<0XFF01||unicode>0XFF61)
return 0x2020;//没有对应编码 //不能显示的字符就给两个空格填充,否则乱码
offset=unicode-0XFF01+0X9FA6-0X4E00;
}
offset *= 2;
f_lseek(&UtoG_File, offset); //文件指针调到偏移位置
if(f_read(&UtoG_File, buff, 2, &bw) != FR_OK) //读取2字节
{
return 0x2020;
}
temp = buff[0];
temp <<= 8;
temp += buff[1];
return temp; //返回找到的编码
}
以上代码引用改博文https://blog.youkuaiyun.com/cp1300/java/article/details/9034289