Android NDK 下的寬字元編碼轉換及icu庫的使用

來源:互聯網
上載者:User

    原貼http://topic.csdn.net/u/20101022/16/1b2e0cec-b9d2-42ea-8d9c-4f1bb8320a54.html?r=70149216 ,看過並動手實現,記錄下來以備再用。

    如果是在java層,有String類可以很好的轉換各種編碼,在ndk下面就沒有現成的公開的工具,不過可以用icu4c。

    ICU4C 是IBM的國際化開發組件ICU的C語言實現版本。在android系統裡也有實現。ndk裡面並沒有公開可用的api,需要自己載入動態庫來調用轉換函式。

    android下icu庫路徑為"/system/lib/libicuuc.so",主要用到的轉換函式為ucnv_convert_?_?。這裡的問號是根據版本的不同函數名也不一樣。在2.2的模擬器中的libicuuc.so中此函數名為ucnv_convert_4_2,在2.1模擬器中為ucnv_convert_3_8,貌似要根據版本不同來分開對待,還沒發現可以統一的辦法。

    函數原型:

    void ucnv_convert(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*);

 

    用法:

    //聲明函數指標<br />void (*ucnv_convert)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*)=0;<br />//載入動態庫<br />void* pDL = dlopen("/system/lib/libicuuc.so", RTLD_LAZY);<br />//這裡以android2.2為例,函數名就是ucnv_convert_4_2<br />ucnv_convert = (void (*)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*))dlsym(pDL, "ucnv_convert_4_2");<br />//載入成功就可以用了<br />if(ucnv_convert){<br /> char* cbuf = "...";<br /> char buffer[100];<br /> int errcode = 0;<br /> //utf8是目標編碼,ucs2是原字元編碼<br /> //buffer是存放轉換出來的字元的緩衝,給了100位元組<br /> //cbuf是要轉換的字串指標<br /> //errcode是錯誤編碼,具體可網上搜尋<br /> ucnv_convert("utf8","ucs2", buffer, 100, cbuf, strlen(cbuf),&errcode);<br />}

 

    轉換成功後的字串就放在buffer裡面,如果出錯了就會在errcode裡面放錯誤碼。

 

    如標題所示,ndk下還有一個寬字元,也就是wchar_t的問題,跟其他平台移植也是個麻煩的事。

    linux下wchar_t預設是4個位元組,而windows下(包括CE,MOBILE)和symbian下都是2個位元組。解決的辦法是在android.mk檔案中,找到LOCAL_CFLAGS 為其加上編譯開關 -fshort-wchar(如果沒有此項就手動寫上),如 LOCAL_CFLAGS :=  -fshort-wchar  。這樣強制編譯器用2個位元組處理wchar_t,不過編譯時間會有warning,可以不管。

    這樣雖然編譯器處理成2個位元組,但是先行編譯的庫libc等依然是4個位元組,會導致wcslen等函數無法使用(其實ndk下wcslen本來就是廢的),解決的辦法可以重新編譯libc,不過最簡單的還是自己實現wcslen就行了。

    下面的代碼是copy網上的,具體哪裡的忘了,可以把wchar_t轉換成char字串,這樣就可以用icu庫隨意轉換了。

 

    //取得wchar_t字串長度<br />int wlen(const wchar_t* strString){<br />int i=0;<br />while (1) {<br />if (strString[i] == 0) {<br />break;<br />}else{<br />i++;<br />}<br />}<br />return i;<br />}</p><p>char *W2C(const wchar_t *pw , char *pc)<br />{<br /> *pc++ = *pw >> 8 ;<br /> *pc = *pw ;<br /> return 0 ;<br />}<br />//轉換字串<br />char *wstr2cstr(const wchar_t *pwstr, char *pcstr, size_t len) {<br />char *ptemp = pcstr;<br />if (pwstr != NULL && pcstr != NULL) {<br />size_t wstr_len = wlen(pwstr);<br />len = (len > wstr_len) ? wstr_len : len;<br />while (len-- > 0) {<br />W2C(pwstr, pcstr);<br />pwstr++;<br />pcstr += 2;<br />}<br />*pcstr = '/0';<br />return ptemp;<br />}<br />return 0;<br />}

 

    使用wstr2cstr就可以轉換出來。這裡還有個位元組序的問題,在W2C函數裡面,一個wchar_t轉到char究竟是低位在前還是高位在前恐怕還是要看轉換前後的編碼具體對待。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.