規避Mac下機器的大小字節序問題

字節序的含義:大於一個字節類型的數據在內存中的存放順序。比如short 或者int在不同的字節序存儲結果是不一樣的。
大字節序(Big-Endian):高位字節排放在內存的低地址端,低位字節排放在內存的高地址端
小字節序(Little-Endian):低位字節排放在內存的低地址端,高位字節排放在內存的高地址端

通過一個簡單的程序來判定該系統是大字節序還是小字節序。

#include <iostream>
int main(){
    int number = 1;
    if(*(char *)&number)
        std::cout<<"Little-endian!\n";
    else
        std::cout<<"Big-endian!\n";
    return 0;
}

該段代碼的原理很簡單。int類型的1,在小字節序下最低位爲1,在大字節序下,最高位爲1。所以可以通過判斷最低位是否爲0來確定該機器的字節序是什麼。
經測試,在Windows,MacOSX,Linux等基於x86的機器上面測試,都是小字節序。

在各種常見編碼(GBK,UTF-8,Unicode)中,只有Unicode會牽扯到字節序這個概念,因爲UCS-2是用short int存儲,UCS-4是用int存儲。
我來用下面這段代碼檢驗一下通過iconv工具做編碼轉化在不同的機器上的效果。

int main(int argc , char ** argv)
{
    iconv_t conveter = iconv_open("UCS-2","GB18030");
    if(conveter== iconv_t(-1)){
        std::cout<<"encode convert not supported!"<<std::endl;
        if(errno==EINVAL)
            std::cout<<"einval"<<std::endl;   
        return -1;   
    }
    else{
        //std::cout<<"ok!"<<std::endl;   
    }

    size_t insize;
    char input[10] = "abcdefg";
    char * inin = input;
    insize=strlen(input);
    //std::cout<<"input is: "<<input<<std::endl;

    size_t outsize = insize * 5+1;
    char *output = new char[outsize];
    char *output_old = output;
    memset(output,0,outsize);        

    size_t ret = iconv(conveter,&inin,&insize,&output_old,&outsize);
    if(ret==(size_t)-1){
        std::cout<<"converting failed"<<std::endl;
        return -1;
    }

    std::ofstream of;
    of.open("yy.txt", std::ios::binary);
    of.write(output, outsize);

    of.close();

    std::cout << output << std::endl;
    std::cout << "outsize=" << outsize << std::endl;

    delete[] output;
    iconv_close(conveter);

    return 0;
}

例子很簡單,將gbk編碼的字符串變成unicode編碼,看轉化後的效果是否跟機器的字節序保持一致。經測試結果發現在MacOSX和Linux下面結果有不同。Linux 的結果是正常的,

0000000: 6100 6200 6300 6400 0000 0000 00 a.b.c.d……

但是在OSX下面的結果卻是這樣:
0000000: 0061 0062 0063 0064 0000 0000 00 .a.b.c.d…..

爲什麼會在兩個平臺如此,具體原因沒有深究。但是這種表現會影響Mac下面的轉化結果。在iconv時顯示的指明到底是UCS-2LE還是UCS-2BE,這樣在各個平臺的處理結果是符合預期的,修改這麼一句:

iconv_t conveter = iconv_open("UCS-2LE","GB18030");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章