jstring 對應java的 String 這個大家都知道 但是jstring 與wchar_t有何關係呢,這是個挺糾結的問題,最近一個項目的jni 的字元處理 全部要使用wchar_t,且要與java 通訊 首先 第一個想法,自然是百度,找到可以通過 GetStringLengthGetStringChars 先擷取到jchar*,轉定義看下jchar定義 16 bits雙位元組,哦耶wchar_t也是雙字元(win下的習慣),這下好解決了直接按網上給的代碼直接強轉 然後memcpy 看樣子分分鐘就解決了。 網上源碼:複製代碼 1 wchar_t* w2js(JNIEnv* env, jstring str) 2 { 3 int len = env->GetStringLength(str); 4 wchar_t *w_buffer = new wchar_t[len]; 5 memset(w_buffer,0,len+1); 6 w_buffer[len]='\0'; 7 wcsncpy(w_buffer,(wchar_t *)env->GetStringChars(str,0),len); 8 env->ReleaseStringChars(str,(const unsigned short *)w_buffer); 9 return w_buffer; 10 }11 複製代碼 測試的確是那麼回事感覺正常的,然後測試了好些字串好英文字元很正常,沒啥問題. 於是開始測試中文, 中文第一次測試 15個字 調試代碼擷取長度15正常,在做完轉換之後,長度就變成11了,尼瑪,被截斷了. 因為是wcsncpy正常理念中應該是不會有問題的,但實際上出的確出現問題,偶爾正常,偶爾有問題缺少字元. 接下來 做了個簡單測試 sizeof(jchar) \ sizeof(wchar_t) 才發現android的wchar_t與jchar使用的位元組完全不一樣,一個2位元組一個4位元組,拷貝過程中估計是因為這個出現了問題. 由於對字元處理沒經驗,基礎知識又不紮實,腫麼辦呢, 糾結了一整天,沒有解決,又糾結了一整天,還是沒有解決,兩天過去了,無意中百度到另外份代碼,通過把指標當成數組的方式來處理的,實際上最後也是通過這種方式來解決的. 處理過程大致如下:java -> String[utf-16(固定雙位元組)] -> jstring-> jchar[固定雙位元組] -> wchar_t[固定四位元組]雙位元組與四位元組之間如何處理呢大家看下記憶體資料 雙字元 0x11 0x12四位元組 0x11 0x12 0x00 0x00看完記憶體資料以後 大家應該明白怎麼回事了吧!~我們只要建立一個與jchar* 長度一樣的 wchar_t*就可以了 然後把他們兩者當作 數組來處理jchar* 每個元素 雙位元組wchar_t* 每個元素 四位元組(且使用的是前兩個位元組) 我們就可以得到下面的代碼 複製代碼 1 //jstring 轉換成 wchar_t 2 //env :JNIEnv jni操作 不可或缺的 3 //jstr:jstring 源字元(來自java) 4 //dst :轉換後的結果,四位元組wchar_t 似乎linux專用 5 //return : 無 6 void js2w(JNIEnv *env,jstring jstr,wchar_t *dst) 7 { 8 //擷取java字串的長度 9 jsize jstr_len = env->GetStringLength(jstr); 10 //擷取java字串的jchar指標 11 const jchar * pjstr = env->GetStringChars(jstr,0); 12 13 tc_char *ptmp = new tc_char[jstr_len+1];14 memset(ptmp,0,sizeof(tc_char) * (jstr_len+1));15 //轉換 以數組的形式把 jchar轉換到wchar_t16 for(int i=0 ;i<jstr_len;i++)17 memcpy(&ptmp[i],&pjstr[i],2);18 19 wcscpy(dst,ptmp);20 delete [] ptmp;21 }複製代碼 然後 wchar_t 轉換jstring 原理只不過是一個逆向的過程,直接上源碼 複製代碼 1 //wchar_t 轉換成 jstring 2 //env :JNIEnv jni操作 不可或缺的 3 //src:wchar_t 源字元 四位元組似乎linux專用 4 //return : 轉換完成以後的結果jstring 5 jstring w2js(JNIEnv *env,wchar_t *src) 6 { 7 int src_len = wcslen(src); 8 jchar * dest = new jchar[src_len+1]; 9 memset(dest,0,sizeof(jchar)*(src_len+1));10 11 for(int i =0 ;i<src_len;i++)12 memcpy(&dest[i],&src[i],2);13 jstring dst = env->NewString(dest,src_len);14 delete [] dest;15 return dst;16 }複製代碼 本身這個轉換是很簡單的,只因為自己不瞭解這兩種類型的本質,從而導致自己走了不少的彎路,但是在解決問題的過程中學到了非常多的東西