Chinaunix首页 | 论坛 | 博客

分类: LINUX

2012-12-28 10:49:42

    Unicode 是一种在计算机上使用的字符编码,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。注意,Unicode 仅仅是定义了一个字符映射表,而没有实现具体的编码。例如:大写字符 ‘A' 的 Unicode 码是 0x41,汉字 “中” 的 Unicode 码是 0x4E2D,这仅仅是一种简单的对应关系,至于如何存储这些 Unicode 码,就是具体编码规则定义的。你可以用 2 个字节来表示 ‘A’ 和 “中” 的 Unicode 码,甚至可以用 3 个字节或 4 个字节,但是不同的编码规则对资源的利用和读写的效率是不一样的。
    对于简体汉字的 Unicode 码,其值是位于 0x4E00 - 0x9FCF 这个范围,具体可以参考 。

    UTF-8(Universal Transformation Format 通用转换格式)是 Unicode 的一种变长字符编码,又称万国码,由 Ken Thompson 于 1992 年创建。现在已经标准化为 RFC 3629。UTF-8 用 1 到 6 个字节编码 Unicode 字符。用在网页上可以同一页面显示中文简体繁体及其它语言(如日文,韩文)。
   
 
UTF-8 编码字节含义:
    对于 UTF-8 编码中的任意字节 B,如果 B 的第一位为 0,则 B 为 ASCII 码,并且 B 独立的表示一个字符;
    如果 B 的第一位为 1,第二位为 0,则 B 为一个非 ASCII 字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码;
    如果 B 的前两位为 1,第三位为 0,则 B 为一个非 ASCII 字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示;
    如果 B 的前三位为 1,第四位为 0,则 B 为一个非 ASCII 字符(该字符由多个字节表示)中的第一个字节,并且该字符由三个字节表示;
    如果 B 的前四位为 1,第五位为 0,则 B 为一个非 ASCII 字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示;
    因此,对 UTF-8 编码中的任意字节,根据第一位,可判断是否为 ASCII 字符;根据前二位,可判断该字节是否为一个字符编码的第一个字节; 根据前四位(如果前两位均为1),可确定该字节为字符编码的第一个字节,并且可判断对应的字符由几个字节表示;根据前五位(如果前四位为1),可判断编码是否有错误或数据传输过程中是否有错误。

例如:汉字“中”的 Unicode 码为 0x4E2D,在 UTF-8 中表示为 0xE4 0xB8 0xAD。
    E4           B8           AD        /* UTF-8 */
1110 0100    1011 1000    1010 1101
     0100      11 1000      10 1101
0100 1110    0010 1101
    4E           2D                     /* UNICODE */

数码相框中
    每一个字符编码器对应一个 struct encode 结构体对象:
struct encode {
    char *name;
    int head_size;
    int (*support)(unsigned char *raw);
    int (*get_code)(unsigned char *head, unsigned char *tail, unsigned int *code);
    struct list_head list;
};

    对于 UTF-8 格式的文本,在文件最开始三个字节处存放的是 EF BB BF。成员
head_size 记录了文件头的大小,对于 UTF-8 格式的文件,其值应为 3。

1.核心层 encode_core.c 简要分析:
static struct list_head encode_list;

/* 必须第一个被调用,用来初始化链表头 */
void encode_core_init(void)
{
    INIT_LIST_HEAD(&encode_list);
}
void register_encode(struct encode *encode)
{
    list_add(&encode->list, &encode_list);
}
struct encode * select_encode(unsigned char *raw)
{
    struct encode *encode;
    struct list_head *pos;
    list_for_each(pos, &encode_list)
    {
        encode = list_entry(pos, struct encode, list);
        if(encode->support(raw))
            return encode;
    }
    return NULL;
}
   
核心层主要提供一些接口供外部函数调用,在使用字符编码器时,必须要先调用 encode_core_init() 函数,它是用来初始化一个链表头,所有系统注册过的字符编码器都会被加入该链表。同样,当读取文本文件的原始数据后,应该使用 select_encode() 函数来选择相应的能处理该文本的字符编码器

2.UTF-8 字符编码器 utf-8.c 简要分析:
struct encode utf8_encode = {
    .name = "utf-8",
    .head_size = 3,    //头部含有3个字节
    .support = utf8_support,   
    .get_code = utf8_get_unicode,   
};
/* 判断该文本是否是 UTF-8 编码格式 */
static int utf8_support(unsigned char *raw)
{
    const char head[] = {0xEF, 0xBB, 0xBF, 0};
    if(strncmp(head, (const char*)raw, 3) == 0)
        return 1;
    else
        return 0;
}
/* 分析某一字符包含的字节数 */
static int analyze_code_info(unsigned char byte)
{
    int i;
    int count = 0;
    for(i=7; i>=0; i--)
    {
        if((byte & (1<            break;
        else
            count++;
    }
    return count;
}
/* 获得某一个字符的 Unicode 码 */
static int utf8_get_unicode(unsigned char *head, unsigned char *tail, unsigned int *code)
{
    int num;
    unsigned char val;
    unsigned int sum = 0;
    int i;   
    if(head >= tail)    /* 文件结束 */   
        return 0;
    num = analyze_code_info(head[0]);
    if ((head + num) > tail)    /* 文件结束 */
        return 0;
    if (num == 0)    /* ASCII */
    {   
        *code = head[0];
        return 1;
    }
    else
    {
        val = head[0] << num;
        val = val >> num;
        sum += val;
        for (i = 1; i < num; i++)
        {
            val = head[i] & 0x3f;
            sum = sum << 6;
            sum += val;           
        }
        *code = sum;
        return num;
    }
}
/* 向系统注册 UTF-8 字符编码器 */
void utf8_encode_register(void)
{
    register_encode(&utf8_encode);
}

int utf8_get_unicode(unsigned char *head, unsigned char *tail, unsigned int *code);
   
utf8_get_unicode() 函数用于获得某一个字符的 Unicode 码,该字符在文件中的存放位置是 head,文件的结束位置是 tail,获得的 Unicode 码存放在参数 code 中,函数返回此编码格式下表示该字符所使用的字节数。

                       ——忠于梦想 勇于实践    linux_xpj@opencores.org

阅读(2069) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~