文档章节

iconv实现编码转换与中文点阵字库HZK16

水海云
 水海云
发布于 2013/02/28 21:48
字数 1285
阅读 1728
收藏 5

嵌入式开发中中文的识别、显示一直是一个比较让人头疼的问题,这是由于嵌入式系统的精简要求所导致的。我在前一个项目中用Qt做终端的显示界面时,就被中文字符的显示搞得焦头烂额,最后还是在网上下了一个文泉驿的中文字体库才解决问题,不过并不令人满意,主要是字体库太大了,影响了性能。今天在项目中又遇到了中文字符的编码转换和显示问题,趁机学习总结一下。

中文编码与点阵字库

国际标准有UTF-8、UTF-16等,国家标准有GB2312、GB18030、GBK等,至于这些标准的编码实现就不在这里介绍了。编码标准实现中文字符在计算机内部的机器表示,但是怎么将这些内部表示在显示设备上显示出来,则不是编码标准的范畴了,这就需要中文字库的作用。中文字库包含已经做好的显示“模板”(字模),通过中文的编码值来映射汉字在字库中的字模索引,从而使用字模来实现中文显示。

但是大部分的中文字库都是映射国家标准的,如GB2312的HZK16点阵字库。不知道文泉驿字体库是否是直接映射UTF-8,还是也是GB2312。因此,当在程序中涉及两种不同的中文编码方式时,就需要进行编码方式的转换,今天我遇到的就是要实现中文字符UTF-8到GB2312的编码转换。

HZK16是符合GB2312标准16*16的点阵宋体字库,支持的汉字有6763个,符号682个。其中一级汉字有 3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。

有关点阵汉字显示的更多了解,可以阅读:点阵汉字显示

iconv命令实现文件编码转换

Linux系统中的iconv命令可以实现一个文件的整体编码转换,详细帮助可以通过man iconv查看。iconv命令的基本格式为:

<!-- lang: shell -->
iconv -f from-encoding -t to-encoding  input-file -o output-file

至于from-encoding和to-encoding的可用值可以通过选项-l进行查看:

<!-- lang: shell -->
iconv -l

可以在输出结果中找到GB2312、UTF-8、GB18030、UTF16。上述的中文编码文件转换:

<!-- lang: shell -->
iconv -f GB2312 -t UTF8 display_utf8.c -o display_gb2312.c

iconv编码转换函数

POSIX.1-2001标准和UNIX 98规范中均包含了iconv编码转换函数族,它们分别是:

<!-- lang: cpp -->
#include <iconv.h>
//成功返回转换句柄,失败返回-1;字符集参考iconv -l命令结果
iconv_t iconv_open(const char *tocode, const char *fromcode);
//成功返回不可逆编码转换的字符数,失败返回-1;查看帮助:man 3 iconv
size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
//成功返回0,失败返回-1
int iconv_close(iconv_t cd);

这三个函数均是从glibc2.1版本开始被引入的,因此使用它们需要有glibc库的支持。这次我们的项目中因为不是用的glibc库,所以没法用它们。不过我还是顺便学习了,下面是我编写的一个简单的实例程序,在这里面还是有一些注意点的,看程序:

<!-- lang: cpp -->
#include <stdio.h>
#include <stdlib.h>
#include <iconv.h>
#include <string.h>

#define OUTLEN 128

int display(char *incode, int len);

int main()
{
        char *string = "开源中国";
        iconv_t cd;
        int inbuf_len = strlen(string);
        char outbuf[OUTLEN];
        char *pin = string;
        char *pout = &outbuf[0];  //用"pout=&outbuf" 会引发SIGSERV信号,导致段错误
        int outbuf_len = OUTLEN;

        memset(outbuf, 0, OUTLEN); //清空输出缓存,否则会有意外结果的
        printf("Originial Data:\n"); //打印转换前的一些参数和信息,以进行比较
        printf("\tpin str: %s, outbuf str:%s\n", pin, outbuf);
        printf("\tinbuf_len=%d, outbuf_len=%d\n", inbuf_len, outbuf_len);
        printf("\tstrlen(outbuf)= %d\n", strlen(outbuf));

        cd = iconv_open("GB2312", "UTF8");
        if(cd == 0)
                return EXIT_FAILURE;
        int count = iconv(cd, &pin, &inbuf_len, &pout, &outbuf_len);
        printf("iconv count : %d\n", count);//观察iconv返回值,理解不可逆转换含义
        iconv_close(cd);

        printf("After Converted Data:\n"); //注意发生变化的变量
        printf("\tpin str: %s, gb2312 str:%s\n", pin, outbuf );
        printf("\tinbuf_len=%d, outbuf_len=%d\n", inbuf_len, outbuf_len);
        printf("\tstrlen(outbuf)= %d\n", strlen(outbuf));

        int i,j;
        for(i = 0; i < strlen(outbuf); i += 2)
        {
                display (outbuf+i, 2); //使用HZK16字库显示GB2312编码的中文点阵
        }

        return EXIT_SUCCESS;
}

int display(char *incode, int len)
{
        int i, j, k;
        char mat[16][2];
        FILE    *HZK=NULL;
        unsigned    char    qh,wh;
        unsigned    long    offset;

        qh=incode[0]-0xa0;//获得区码,中文编码从0xA1开始
        wh=incode[1]-0xa0;   //获得位码,中文编码从0xA1开始
        offset=(94*(qh-1)+(wh-1))*32; //得到汉字在HZK16字库中的字节偏移位置
        printf("区码:%d,位码:%d\n",qh,wh);

        if((HZK=fopen("HZK16","rb")) ==NULL)
        {
           perror("Can't Open hzk16");
           return (EXIT_FAILURE);
        }
        fseek(HZK,offset,SEEK_SET);
        fread(mat,32,1,HZK);//读取汉字的16*16点阵字模
        fclose(HZK);

        for(i = 0; i < 16; i++)  //显示点阵
        {
                for(j = 0; j < 2; j++)
                        for(k = 0; k < 8; k++)
                        {
                                if(mat[i][j] & (0x80>>k))
                                        printf("*");
                                else
                                        printf(" ");
                        }
                printf("\n");
        }

        return EXIT_SUCCESS;
}

运行程序,观察一下输出,能让我们更好地理解iconv函数: 示例程序输出

© 著作权归作者所有

水海云
粉丝 50
博文 120
码字总数 101938
作品 0
深圳
程序员
私信 提问
用Python写一份独特的元宵节祝福

今天是正月十五,首先祝大家元宵节快乐! 以前加过我个人VX号的朋友,可以在朋友圈看到我今天发的元宵节祝福图片: 这个祝福文字乍一看其貌不扬,不过点开大图有惊喜:是拿自己VX好友的头像拼...

crossin
02/19
53
0
【物联网智能网关-08】TinyGUI和WPF汉字显示技术比较

TinyGUI是我在2010上半年的时候,基于.NET Micro Framework系统开发的一个轻量级图形库,虽然TinyGUI运行需要的资源少,运行快,但是不支持汉字显示(如需显示汉字还是必须借助WPF本身的功能...

yefanqiu
2012/08/15
0
0
制作字库(Bin文件合并 C2BIN)

一、点阵文件生成 1、使用点阵字库生成器生成文字的点阵信息,采用 UNICODE 编码批量生成。 2、如果具有 C 文件的字库,例如 STM32 开发板的库函数 中的字库 C 文件,可以使用 C2B转换助手,...

u011303443
2017/04/06
0
0
点阵字库在JAVA中的实现

前言:为什么要使用点阵字库 在某些场合,系统自带的字库并不能令人满意,或者,在你需要特别的字体时,你希望能附带上该字库。 那为什么又需要点阵字库呢?因为在使用较小的字体的时候,点阵...

长平狐
2012/10/09
1K
0
IE浏览器与FF浏览器关于 Ajax传递参数值为中文时的区别

Ajax传递参数为中文时出现乱码,我遇到的情况是: 1.我的数据库连接 编码为 GB2312,latin1swedishci 2.php 文件编码格式为 UTF-8,浏览器显示编码为 : UTF-8 3.我的页面显示方式为两种: ...

LiMXHS
2013/08/21
1K
6

没有更多内容

加载失败,请刷新页面

加载更多

centos7上部署dubbo管理控制台dubbo-admin

centos7上部署dubbo管理控制台dubbo-admin 1 准备工作 服务器:系统centos7, 内存4G, 存储60G, ip 192.168.159.128 软件环境: 安装有jdk1.8, 具体安装方式参见《centos7上安装jdk1.8》博...

flygrk
20分钟前
5
0
工作中一些原则体会

尽可能让一切变得简单,用最简单的方式完成工作 能用最少的概念,最精简易懂的概念模型来抽象系统,多一个概念就多一份别人了解系统以及维护系统的复杂度,别人也会质疑多一个概念的意义所在...

小强的进阶之路
24分钟前
5
0
Android -------- kotlin插件神器Json直接生成javaBean

这是一个data class从JSON字符串生成Kotlin 的插件,换句话说,是一个将JSON字符串转换为Kotlin data class(Json到Kotlin)的插件 在使用Kotlin进行开发的时候,我们需要经常对Json数据做解析...

切切歆语
49分钟前
31
0
1、Spring注解开发,第一天

第一天:Spring annotation开发 目录:1、@Configuration与@Bean给容器注册组件 2、@ConponentScan自动扫描注解 一、@Configuration与@Bean给容器注册组件 1、旧版本中创建配置文件和Bean //...

有一个小阿飞
57分钟前
24
0
斯坦福博弈论笔记整理活动的任务已重新划分,望周知

参与方式:https://github.com/apachecn/stanford-game-theory-notes-zh/blob/master/CONTRIBUTING.md 整体进度:https://github.com/apachecn/stanford-game-theory-notes-zh/issues/1 项目......

ApacheCN_飞龙
58分钟前
23
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部