Feeling

              三人行,必有我?guī)熝?/p>

             ::  :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
            185 隨筆 :: 0 文章 :: 392 評論 :: 0 Trackbacks
          網(wǎng)上有一篇關(guān)于JNI中文問題的文章,寫得很詳細(xì),http://www.vckbase.com/document/viewdoc/?id=1611

          我在這里主要是想說說我碰到的一些問題,并且希望能從各位老大身上獲得答案。

          因為一直從事Java編程,基本上沒有涉及過C++的開發(fā),最近因為開源項目SWT Extension,不得已需要用JNI來實現(xiàn)一些系統(tǒng)Native功能。但是總是需要一些Java字符串對應(yīng)C++的字符串的問題。一邊情況下我都是使用SWT的TCHAR來解決問題,少部分情況需要傳遞Java String到JNI。然而少部分的這些Case總是在某些問題下出現(xiàn)亂碼或者異常。我一直使用的是網(wǎng)上比較流行的中文編碼解決方案:
          char* jstringToNative( JNIEnv  *env, jstring jstr )
          {
            
          int length = env->GetStringLength(jstr );
            
          const jchar* jcstr = env->GetStringChars(jstr, 0 );
            
          char* rtn = (char*)malloc( length*2+1 );
            
          int size = 0;
            size 
          = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
            
          if( size <= 0 )return NULL;
            env
          ->ReleaseStringChars(jstr, jcstr );
            rtn[size] 
          = 0;
            
          return rtn;
          }

          jstring nativeTojstring( JNIEnv
          * env, char* str )
          {
            jstring rtn 
          = 0;
            
          int slen = strlen(str);
            unsigned 
          short * buffer = 0;
            
          if( slen == 0 )
              rtn 
          = env->NewStringUTF( str ); 
            
          else
            {
              
          int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
              buffer 
          = (unsigned short *)malloc( length*2 + 1 );
              
          if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
                rtn 
          = env->NewString(  (jchar*)buffer, length );
            }
            
          if( buffer )
            free( buffer );
            
          return rtn;
          }

          一般情況下,這兩個函數(shù)能夠很好的工作。但是在讀寫注冊表時,如果一個key的名字或者value的名字中包含了中文,jstringToNative的解決方案是不正確的,我在網(wǎng)上查了一下其它的關(guān)于Java訪問注冊表的開源項目,發(fā)現(xiàn)雖然它們都對字符串進(jìn)行了處理,但依然存在著中文問題。我進(jìn)行了數(shù)次嘗試,但都沒有成功。最后到了已經(jīng)絕望的時候,用開頭我提到的那篇文章中里說的最不可能用到的方法將問題成功地解決了:
          char* jstringToNative( JNIEnv  *env, jstring jstr )
          {
            
          const char* pstr = env->GetStringUTFChars(jstr, false);
            
          int nLen = MultiByteToWideChar( CP_UTF8, 0, pstr, -1, NULL, NULL );
            LPWSTR lpwsz 
          = new WCHAR[nLen];    
            MultiByteToWideChar( CP_UTF8, 
          0, pstr, -1, lpwsz, nLen );
            
          int nLen1 = WideCharToMultiByte( CP_ACP, 0, lpwsz, nLen, NULL, NULL, NULL, NULL );    
            LPSTR lpsz 
          = new CHAR[nLen1];
            
          int size = 0;
            size 
          = WideCharToMultiByte( CP_ACP, 0, lpwsz, nLen, lpsz, nLen1, NULL, NULL );
            
          if( size <= 0 ){
                delete [] lpwsz;
                
          return NULL;
            }
            env
          ->ReleaseStringUTFChars(jstr, pstr );
            delete [] lpwsz;
            
          return lpsz;
          }
          問題雖然解決了,但是我卻不求甚解,為什么直接通過env拿到unicode字串,然后轉(zhuǎn)成多字節(jié)串不行,但是通過env拿到utf-8字串,然后轉(zhuǎn)成unicode字串,再將這個unicode字串轉(zhuǎn)成多字節(jié)串就能工作?

          如果大家有興趣的話,不妨試試,用JNI調(diào)用RegOpenKeyEx這個API,就能驗證我說的這個Case。哪位老大對JNI比較在行的話,可以在評論中告訴我,不甚感激。

          評論

          # re: JNI的中文問題 2008-05-04 15:41 Unmi
          看到了,還是需要用
          MultiByteToWideChar
          WideCharToMultiByte

          這兩個寬窄字符轉(zhuǎn)換的的 API 函數(shù)。  回復(fù)  更多評論
            

          # re: JNI的中文問題 2008-05-04 17:40 笨笨
          考慮到跨平臺兼容問題,可以考慮用ICU庫.
          更加簡單的辦法:
          先用String.getBytes()方法將String轉(zhuǎn)為byte數(shù)組給C代碼. 返回時用 new String(byte[]) 將字節(jié)數(shù)組轉(zhuǎn)為String對象.
            回復(fù)  更多評論
            


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          GitHub |  開源中國社區(qū) |  maven倉庫 |  文件格式轉(zhuǎn)換 
          主站蜘蛛池模板: 长顺县| 潼南县| 老河口市| 会宁县| 东兰县| 余江县| 嘉善县| 清水县| 临猗县| 连江县| 胶南市| 临沂市| 扶沟县| 儋州市| 娄底市| 遵义县| 天等县| 临泉县| 铅山县| 信阳市| 阳信县| 锡林郭勒盟| 宁阳县| 宁夏| 五寨县| 德昌县| 牡丹江市| 府谷县| 沙洋县| 高雄县| 武冈市| 汽车| 荣成市| 新津县| 松江区| 崇义县| 米易县| 拉萨市| 昂仁县| 出国| 昌平区|