iconv實現編碼轉換與中文點陣字庫HZK16

嵌入式開發中中文的識別、顯示一直是一個比較讓人頭疼的問題,這是因爲嵌入式系統的精簡要求所致使的。我在前一個項目中用Qt作終端的顯示界面時,就被中文字符的顯示搞得焦頭爛額,最後仍是在網上下了一個文泉驛的中文字體庫才解決問題,不過並不使人滿意,主要是字體庫太大了,影響了性能。今天在項目中又遇到了中文字符的編碼轉換和顯示問題,趁機學習總結一下。shell

中文編碼與點陣字庫

國際標準有UTF-八、UTF-16等,國家標準有GB23十二、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

能夠在輸出結果中找到GB23十二、UTF-八、GB18030、UTF16。上述的中文編碼文件轉換:.net

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

iconv編碼轉換函數

POSIX.1-2001標準和UNIX 98規範中均包含了iconv編碼轉換函數族,它們分別是:code

<!-- 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庫,因此無法用它們。不過我仍是順便學習了,下面是我編寫的一個簡單的實例程序,在這裏面仍是有一些注意點的,看程序:blog

<!-- 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函數: 示例程序輸出

相關文章
相關標籤/搜索