Chinaunix首页 | 论坛 | 博客
  • 博客访问: 486765
  • 博文数量: 53
  • 博客积分: 492
  • 博客等级: 下士
  • 技术积分: 866
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-14 15:12
文章分类

全部博文(53)

文章存档

2016年(1)

2015年(3)

2014年(17)

2013年(9)

2012年(7)

2011年(16)

我的朋友

分类: C/C++

2011-12-21 09:26:54

:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://zongtongyi.blogbus.com/logs/105776527.html

iconv编码转换与字节序有什么关系?为什么UTF8没有字节序的烦恼?

为什么UTF8不用关心字节序?网上找不到详细说明,引用论坛上一句抱怨的话:
但是查了N多网页,大家都很坦然的说“UTF-8以字节为编码单元,没有字节序的问题。”,当凭它是字节为编码单元,就没有字节序问题了?这话说的也太厚脸皮了吧。
是啊,没有详细点的说明啊,只有自己纠结啊。

首先引入一个程序
#include
#define LEN 100
int main(int argc,char *argv[]){
    iconv_t cd = iconv_open("UTF-8", "zh_TW.big5");    // use UTF-16LE or UTF-16BE
    if (cd == (iconv_t) - 1) {
        printf("open convert library failed.\n");
        exit(1);
    }

    char *pIn, *pOut;
    unsigned int inLen, outLen;

    char encode[]={0x88, 0xEE};
    inLen=2;

    char outbuf[LEN];
    memset(outbuf, '\0', LEN);
    pIn=encode;
    pOut=outbuf;
    outLen=LEN;
    size_t ret;
    ret = iconv(cd, &pIn, &inLen, &pOut, &outLen );
    if (ret == (size_t)-1) {
        fprintf(stdout, "\nconvert failed\n\n");
        return false;
    }

    fprintf(stdout, "\nconvert success\n\n", "  ");
    return (EXIT_SUCCESS);
} (函数体和头文件有删减,可以自己适当添加后编译)
解释一下这个程序,这个程序调用系统提供的iconv库来转换编码,其中encode[]数组里是一个big5的编码(这个字的编码是两个字节的,这里用 16进制表示),程序调用iconv库将这个big5编码转换成utf8编码。如果转换成功,则输出“convert success”,否则输出“convert failed”。
第一个猜想 :只有UTF8编码不需要关心字节序吗?
问Jacky后得出结论,so far,我们只知道UTF16需要关心字节序,其它全不需要。
论证一下,只有UTF16的编码单元是双字节的,其它都是单字节的。(又是那个后颜的说法!)
第二个猜想 :那个encode[]在big endian和little endian中的存储方式有什么不同吗?
当然,你可以用C语言来解释。不喜欢,来点实验派吧。
在Solaris中,用dbx调试一下,实验机器分别是一台Sparc,一台x86,Sparc是big endian,x86是little endian。
根据实验结果,不论是Sparc,还是x86,从内存地址上,encode[2] > encode[1] > encode[0]
也就是说不论是big endian还是little endian,数组都是递增存储的。(挺废话的)
有以上铺垫后延伸:根据iconv源码,iconv读入调用者给出的inbuffer地址,然后递增的去分析每个字节 (i++)
例:gbk_encode[2]={0x8F, 0xEC}; 其中gbk_encode[0]存在内存地址0x000081,则gbk_encode[1]存在内存地址0x000082
首先,不论big endian还是little endian,数组在内存中都是这么递增存储的,
其次,不论big endian还是little endian,iconv源码都是从内存中递增去读取数据的,
则,不论big endian还是little endian,读出来的都是相同的结果,
所以,我们证明了:单字节编码的字符集,不需要考虑字节序问题。
那...双字节为什么不一样呢?
第三个猜想 :一个汉字,在big endian机器上存储到文件里,与little endian有什么不一样的?
麻烦,随便找台机器,打开gedit,输入“我”,分别以“Unicode(UTF-16BE)”和“Unicode(UTF-16LE)”两种编码方式保存,即分别按big endian和little endian方式存储。
文件名分别为be和le,再用gedit打开,当然,还是看到“我”字,因为gedit能自动识别编码嘛。
怎么看呢?用vi,“vi -b be”和“vi -b le”,以二进制方式打开,进入vi后,输入命令":%!xxd",回车,则看到了改文件对应的二进制,
be文件的二进制是:6211
le文件的二进制是:1162
明白了吗,还没明白,对啊,看iconv源码,UTF16对应的实现文件是UTF8%...,通过条件编译来编译出UTF16_BE等的版本,不细说这个,看代码,当处理little endian的时候,iconv对inbuffer的处理是反过来读的。
该下班了,差不多就这样了。

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