成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JNI和C++通信中文亂碼的問題

開發 后端
從Java1.1開始,JNI標準成為Java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI一開始是為了本地已編譯語言,尤其是C和C++而設計的,但是它并不妨礙你使用其他語言,只要調用約定受支持就可以了。

首先,需要明確幾個關于編碼的基本概念:

◆  java內部是使用的16bit的unicode編碼(utf-16)來表示字符串的,無論英文還是中文都是2字節;

◆ jni內部是使用utf-8編碼來表示字符串的,utf-8是變長編碼的unicode,一般ascii字符是1字節,中文是3字節;

◆ c/c++使用的是原始數據,ascii就是一個字節,中文一般是GB2312編碼,用2個字節表示一個漢字。

jni的中文字符串處理

先從字符流的方向分別對java-->C++和C++-->java進行分析

◆ java-->C++

這種情況下,java調用的時候使用的是utf-16編碼的字符串,jvm把這個參數傳遞給jni,C++得到的輸入是jstring,此時,可以利用jni提供的兩種函數,一個是GetStringUTFChars,這個函數將得到一個UTF-8編碼的字符串;另一個是GetStringChars這個將得到UTF-16編碼的字符串。無論那個函數,得到的字符串如果含有中文,都需要進一步轉化成GB2312的編碼。

  1.        String  
  2.       (UTF-16)  
  3.           |  
  4. [java]    |  
  5. --------------------  JNI 調用  
  6. [cpp]     |  
  7.           v  
  8.        jstring  
  9.        (UTF-16)  
  10.           |     
  11.  +--------+---------+   
  12.  |GetStringChars    |GetStringUTFChars  
  13.  |                  |  
  14.  v                  v  
  15. wchar_t*           char*  
  16. (UTF_16)           (UTF-8) 

◆  c/c++ –> java

jni返回給java的字符串,c/c++首先應該負責把這個字符串變成UTF-8或者UTF-16格式,然后通過NewStringUTF或者NewString來把它封裝成jstring,返回給java就可以了。

  1.        String  
  2.       (UTF-16)   
  3.           ^   
  4.           |  
  5. [java]    |  
  6. --------------------  JNI 返回  
  7. [cpp]     |       jstring  
  8.        (UTF-16)  
  9.           ^  
  10.           |  
  11.  +--------+---------+  
  12.  ^                  ^  
  13.  |                  |  
  14.  |NewString         |NewStringUTF  
  15. wchar_t*          char*  
  16. (UTF_16)          (UTF-8) 

如果字符串中不含中文字符,只是標準的ascii碼,那么用GetStringUTFChars/NewStringUTF就可以搞定了,因為這種情況下,UTF-8編碼和ascii編碼是一致的,不需要轉換。

但是如果字符串中有中文字符,那么在c/c++部分進行編碼轉換就是一個必須了。我們需要兩個轉換函數,一個是把UTF8/16的編碼轉成GB2312;一個是把GB2312轉成UTF8/16。

這里要說明一下:linux和win32都支持wchar,這個事實上就是寬度為16bit的unicode編碼UTF16,所以,如果我們的 c/c++程序中完全使用wchar類型,那么理論上是不需要這種轉換的。但是實際上,我們不可能完全用wchar來取代char的,所以就目前大多數應用而言,轉換仍然是必須的。

具體的轉換函數,linux和win32都有一定的支持,比如glibc的mbstowcs就可以用來把 GB2312編碼轉成UTF16,但是這種支持一般是平臺相關的(因為c/c++的標準中并沒有包括這部分),不全面的(比如glibc就沒有提供轉成 UTF8的編碼),不獨立的(linux下mbstowcs的行為要受到locale設置的影響)。所以我推薦使用iconv庫來完成轉換。

iconv庫是一個免費的獨立的編碼轉換庫,支持很多平臺,多種編碼(事實上,它幾乎可以處理我們所使用的所有字符編碼),而且它的行為不受任何外部環境的影響。iconv在*nix平臺上,基本上是缺省安裝的。在win32平臺上需要額外安裝。

下面提供一個把GB2312編碼的字符串轉換成UTF8編碼的示例

  1. #include <iconv.h>char* BytesToUtf8(string src, char* dst, int* nout) {    size_t n_in = src.length();    size_t n_out = *nout;        iconv_t c = iconv_open("UTF-8""GB2312");    if (c == (iconv_t)-1) {        cerr << strerror(errno) << endl;        return NULL;}   
  2.    
  3.    
  4. char* inbuf = new char [n_in + 1];  
  5.  if (!inbuf) {  
  6.  iconv_close(c);  
  7.  return NULL;  
  8.  }  
  9.    
  10. strcpy(inbuf, src.c_str());  
  11.  memset(dst, 0, n_out);  
  12.    
  13. char* in = inbuf;  
  14.  char* out = dst;  
  15.  if (iconv(c, &in, &n_in, &out, &n_out) == (size_t)-1) {  
  16.  cerr << strerror(errno) << endl;  
  17.  out = NULL;  
  18.  }  
  19.  else {  
  20.  n_out = strlen(dst);  
  21.  out = dst;  
  22.  }  
  23.    
  24. iconv_close(c);  
  25.  *nout = n_out;  
  26.  delete[] inbuf;  
  27.    
  28. return out;  

補充幾點說明:

1、從jni的接口看,jni提供了UTF16和UTF8兩個系列的字符串處理函數,但是由于jni的文檔中說,jni的內部實現中是用UTF8作為字符串編碼格式的,所以使用UTF8系列比較合適(NewStringUTF/GetStringUTFChars /ReleaseStringUTFChars)

2、使用iconv庫的話,運行環境的設置對于編碼轉換是沒有影響的,但是外層java程序對于字符串的解析依賴于運行環境的locale,所以設置正確的locale對于jni意義不大,但是對整個系統還是必要的。

以上是主要是說明使用第三方庫去解決編碼問題,針對僅在windows平臺下,是可以使用windows提供的相關方法進行編碼轉換的。

使用一下方法可以將jstring轉換為char*,主要用于在C++中接收java傳遞過來的參數時包含中文字符時使用。在轉換過程中已經對編碼進行了轉換,可以正常返回出中文字符。

  1. char * JStringToWindows(JNIEnv * pJNIEnv, jstring jstr)  
  2. {  
  3.     jsize len = pJNIEnv->GetStringLength(jstr);  
  4.     const jchar * jcstr = pJNIEnv->GetStringChars(jstr, NULL);  
  5.     int size = 0;  
  6.     char * str = (char *)malloc(len * 2 + 1);  
  7.     if ((size = WideCharToMultiByte(CP_ACP, 0, LPCWSTR(jcstr), len, str, len * 2 + 1, NULL, NULL)) == 0)  
  8.         return NULL;  
  9.     pJNIEnv->ReleaseStringChars(jstr, jcstr);  
  10.     str[size] = 0;  
  11.     return str;  

注意:以上方法中返回的char*在使用過后需要delete釋放,因為在編碼轉換過程中使用了malloc分配了內存,不釋放會發生內存泄漏。

如果需要在C++中返回中文信息給java,則需要以下方法將char*轉換成jstring。

  1. jstring WindowsTojstring( JNIEnv* env, char* str )  
  2. {  
  3.     jstring rtn = 0;  
  4.     int slen = strlen(str);  
  5.     unsigned short * buffer = 0;  
  6.     if( slen == 0 )  
  7.         rtn = (env)->NewStringUTF(str );   
  8.     else 
  9.     {  
  10.         int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );  
  11.         buffer = (unsigned short *)malloc( length*2 + 1 );  
  12.         if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )  
  13.             rtn = (env)->NewString(  (jchar*)buffer, length );  
  14.     }  
  15.     if( buffer )  
  16.         free( buffer );  
  17.     return rtn;  

根據前面的字符流的分析,和后面提供的轉換方法,基本上可以解決jni中中文參數亂碼的問題。

以上內容部分摘自網絡。屬于個人總結內容。

原文鏈接:http://www.cnblogs.com/bluesky4485/archive/2011/12/13/2285802.html

【編輯推薦】

  1. 從Java的角度理解Ext的extend
  2. Windows 64位環境的Java服務配置
  3. 解讀Java環境變量配置
  4. 利用JavaMail API 解析MIME
  5. 詳細解析Java中抽象類和接口的區別

 

責任編輯:林師授 來源: bluesky的博客
相關推薦

2010-06-07 11:13:46

MySQL中文亂碼

2010-06-09 14:54:29

2010-06-02 16:36:38

連接MySQL中文亂碼

2014-09-19 10:46:36

LuaCC++

2009-06-30 13:49:21

excel文檔Jsp

2018-12-07 08:38:49

代理服務器Web服務器通信

2010-11-09 17:09:23

SQL Server中

2011-02-24 10:48:51

FireFTP

2009-11-26 16:30:52

Suse中文亂碼問題

2022-12-06 13:02:27

深度學習AI

2010-06-03 10:26:29

開發MySQL中文亂碼

2024-03-11 06:05:00

C++字符串

2021-09-23 14:41:58

鴻蒙HarmonyOS應用

2010-09-07 16:34:31

統一通信sip

2011-06-09 14:13:06

C++JAVA缺省初始化

2012-05-09 09:56:04

WP7亂碼

2011-08-08 10:29:12

MySQL

2010-03-18 17:18:12

Python 中文亂碼

2011-04-11 09:43:25

C++C

2009-09-01 15:24:59

C++、C#和JAVA
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一级黄大片 | 欧美成人免费在线视频 | 一级高清免费毛片 | 伊人无码高清 | 久久久精品视频一区二区三区 | 黄色国产视频 | 国产在线观看一区二区三区 | 国产精品久久久久久妇女6080 | 美国av片在线观看 | 日韩成人在线观看 | 久久国产精品免费一区二区三区 | 亚洲视频在线观看 | 羞羞的视频免费看 | 日本理论片好看理论片 | 亚洲网站在线观看 | 午夜男人免费视频 | 成人在线影视 | 一区二区三区观看视频 | 日韩三区在线 | 午夜精品一区二区三区免费视频 | 精品国产一区二区国模嫣然 | 国产区精品视频 | 欧美精品在线看 | 米奇7777狠狠狠狠视频 | 美女久久 | 欧美一区二区三区在线观看 | 亚洲免费婷婷 | 亚洲精品福利视频 | 老头搡老女人毛片视频在线看 | 久久久久久国 | 午夜影院污 | 波多野结衣二区 | 91精品国产91综合久久蜜臀 | 精品欧美 | 久久国产欧美日韩精品 | 亚洲精品成人 | 精品在线一区 | 欧美日韩国产一区二区三区 | 国产伦精品一区二区三区精品视频 | 免费视频一区二区 | 国产不卡视频在线 |