首先,需要明确几个关于编码的基本概念:

创新互联是一家专业提供长宁企业网站建设,专注与成都网站制作、网站建设、外贸网站建设、H5场景定制、小程序制作等业务。10年已为长宁众多企业、政府机构等服务。创新互联专业网站建设公司优惠进行中。
◆ 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的编码。
- String
 - (UTF-16)
 - |
 - [java] |
 - -------------------- JNI 调用
 - [cpp] |
 - v
 - jstring
 - (UTF-16)
 - |
 - +--------+---------+
 - |GetStringChars |GetStringUTFChars
 - | |
 - v v
 - wchar_t* char*
 - (UTF_16) (UTF-8)
 
◆ c/c++ –> java
jni返回给java的字符串,c/c++首先应该负责把这个字符串变成UTF-8或者UTF-16格式,然后通过NewStringUTF或者NewString来把它封装成jstring,返回给java就可以了。
- String
 - (UTF-16)
 - ^
 - |
 - [java] |
 - -------------------- JNI 返回
 - [cpp] | jstring
 - (UTF-16)
 - ^
 - |
 - +--------+---------+
 - ^ ^
 - | |
 - |NewString |NewStringUTF
 - wchar_t* char*
 - (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编码的示例
- #include
 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;} - char* inbuf = new char [n_in + 1];
 - if (!inbuf) {
 - iconv_close(c);
 - return NULL;
 - }
 - strcpy(inbuf, src.c_str());
 - memset(dst, 0, n_out);
 - char* in = inbuf;
 - char* out = dst;
 - if (iconv(c, &in, &n_in, &out, &n_out) == (size_t)-1) {
 - cerr << strerror(errno) << endl;
 - out = NULL;
 - }
 - else {
 - n_out = strlen(dst);
 - out = dst;
 - }
 - iconv_close(c);
 - *nout = n_out;
 - delete[] inbuf;
 - 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传递过来的参数时包含中文字符时使用。在转换过程中已经对编码进行了转换,可以正常返回出中文字符。
- char * JStringToWindows(JNIEnv * pJNIEnv, jstring jstr)
 - {
 - jsize len = pJNIEnv->GetStringLength(jstr);
 - const jchar * jcstr = pJNIEnv->GetStringChars(jstr, NULL);
 - int size = 0;
 - char * str = (char *)malloc(len * 2 + 1);
 - if ((size = WideCharToMultiByte(CP_ACP, 0, LPCWSTR(jcstr), len, str, len * 2 + 1, NULL, NULL)) == 0)
 - return NULL;
 - pJNIEnv->ReleaseStringChars(jstr, jcstr);
 - str[size] = 0;
 - return str;
 - }
 
注意:以上方法中返回的char*在使用过后需要delete释放,因为在编码转换过程中使用了malloc分配了内存,不释放会发生内存泄漏。
如果需要在C++中返回中文信息给java,则需要以下方法将char*转换成jstring。
- jstring WindowsTojstring( 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;
 - }
 
根据前面的字符流的分析,和后面提供的转换方法,基本上可以解决jni中中文参数乱码的问题。
以上内容部分摘自网络。属于个人总结内容。
                网页题目:JNI和C++通信中文乱码的问题
                
                标题网址:http://www.csdahua.cn/qtweb/news16/408016.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网