zoukankan      html  css  js  c++  java
  • 左右c++与java中国的垃圾问题的分析与解决

    左右c++与java中国的垃圾问题的分析与解决

    DionysosLai(906391500@qq.com)  2014/8/1

    问题分析:

             之所以会出现中文乱码问题,归根结底在于中文的编码与英文的编码方式存在差异。

             在java内部是使用16bit的unicode编码(即utf-16)来表示字符串。不管英文还是中文都是2字节。

             C/C++使用的是原始数据,ascii是一个字节,中文通常是GB2312编码,用2个字节表示一个汉字。

             Jni内部是使用utf-8编码表示字符串的,utf-8是扁长的unicode。一般ascii是1字节。中文是3字节。


             以下给出在不同字符集编码下的字节数:

              英文字母:

                       字节数 : 1;编码:GB2312              字节数: 1;编码:GBK            字节数 : 1;编码:GB18030

                      字节数 : 1;编码:ISO-8859-1        字节数: 1;编码:UTF-8         字节数 : 4;编码:UTF-16

                      字节数 : 2;编码:UTF-16BE           字节数: 2;编码:UTF-16LE


             中文汉字:

                      字节数 : 2;编码:GB2312              字节数: 2;编码:GBK            字节数 : 2;编码:GB18030

                      字节数 : 1;编码:ISO-8859-1        字节数: 3;编码:UTF-8         字节数 : 4;编码:UTF-16

                       字节数 : 2;编码:UTF-16BE           字节数: 2;编码:UTF-16LE

    二者数据传递分析:

             Java->C++数据传递

             有上文可知,java使用的是utf-16编码。jvm把数据传递给jni,c++dedao的是输入參数u是jstring。此时,能够利用jni提供的两种函数,一个是GetStringUTFChars,这个函数将得到一个UTF-8编码的字符串;还有一个是GetStringChars这个将得到UTF-16编码的字符串。不管那个函数,假设字符串包括中文,都须要进一步转化成CC++的编码格式:GB2312。


    C++->java数据传递

             CC++的英文编码方式是ascii码,对于中文则是GB2312。Jni返回给java的字符串,cc++首先应该负责把这个字符串扁长utf-8或者utf-16格式,然后通过NewStringUTF或者NewString将字符串封装成jstring,返回给java就可以。

             假设没有中文字符,就仅仅有标准的ascii码值,那么使用GetStringUTFChars/NewStringUTF能够轻松搞定。由于在这样的情况下。utf-8编码和ascii编码是一致,不须要转换。

             假设存在中文字符。那么在CC++部分进行编码就是必须的,一个是把utf-8/16的编码转成GB2312。一个是把GB2312转成utf-8/16。

    问题解决:

             最终到解决这个问题的时刻了。(我的大斧已经饥渴难耐了)。

             对于编码转换,推荐使用iconv库,iconv库是一个免费独立的编码转化库。支持多种平台。多种编码,并且其行为不论什么不受外部环境影响。使用iconv库的另外一个优点就是cocos2dx在win32平台下已经集成了其库环境,不须要开发人员额外加入。可是在Android平台就须要开发人员自己加入。至于怎样在Android平台上加入iconv库,在以下会具体解说(也能够看网上教程。基本方法都是怎样在Eclipse上加入库)。

             以下给出怎样将中文编码格式GB2312,转化成utf-8编码方式。

    int CCDirector::GBKToUTF8(std::string &gbkStr)
    {
    	iconv_t iconvH;    
    
    	iconvH              = iconv_open("utf-8","gb2312");    
    	if(iconvH == 0){    
    		return -1;    
    	}    
    	const char* strChar = gbkStr.c_str();    
    	const char** pin    = &strChar;    
    
    	size_t strLength    = gbkStr.length();    
    	char* outbuf        = (char*)malloc(strLength*4);    
    	char* pBuff         = outbuf;    
    	memset(outbuf,0,strLength*4);    
    	size_t outLength    = strLength*4;    
    <span style="color:#ff6666;"><strong>#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
    	if(-1 == iconv(iconvH,pin,&strLength,&outbuf,&outLength)){    
    		iconv_close(iconvH);    
    		return -1;    
    	} 
    #else
    	if(-1 == iconv(iconvH,(char **)pin,&strLength,&outbuf,&outLength)){    
    		iconv_close(iconvH);    
    		return -1;    
    	} 
    #endif</strong></span>
       
    	gbkStr              =   pBuff;    
    	iconv_close(iconvH);    
    	return 0;    
    }
    

             注意红色字体代码,在win32平台和android平台传递的參数是不一样的。这个主要原因是因为pin參数是constchar**型,在java中,没有这样的类型參数。因此要强制装换成char**类型。

    在Eclipse中加入iconv库

             Iconv库下载地址例如以下:

             Cocos2dx引擎在win32平台,本身自带了iconv库,库地址在E:EngilshLogicGameEnglishGamecocos2d-x-2.2.3cocos2dxplatform hird_partywin32,在这里面还包含其它的一些库文件,例如说网络库,解析png库等。引擎在Android平台,没有自带iconv库(个人推測原因是因为ndk自带iconv库了,因此事实上能够不用自己下载iconv库,但这里。我们给出方法是使用自己下载的iconv库),iconv库的下载地址上文已经给出。

             通过更改projectproj.android/jni/Android.mk文件,将iconv库文件载入进Eclipse中。在mk文件里增加了以下两句话,如图所看到的:


             注意:这里我将下载的iconv库文件放在了引擎的external文件下(当然,也能够发在别的地方,仅仅须要更改相应的文件夹文件就可以),如图所看到的:


             下一步。是要更改我们下载的iconv库文件里的mk文件(假设是从我这下载的iconv库,我已经更改好了)。

             更改方式,如图所看到的:

             注意:画圈的两个keyword,与之前改动的proj.android/jni/Android.mk文件里的keyword是一致的。

             到这里,iconv库在Android平台就加入完成了。

             在之前给出的函数GBKToUTF8中。用到了iconv库函数,因此在文件里要包括iconv头文件,详细代码例如以下所看到的:

    #if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
    #include "iconv.h"
    #else
    #include "../external/libiconv/include/iconv.h"
    #endif
    

             

             至此,关于“关于c++与java中文乱码问题分析与解决”话题。就到此为止。希望能对大家有点帮助。

    也感谢公司的同事给帮助到,一些博客和在线。



    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    Android见招拆招十:Migrate Android Code
    Android转载三:(布局)ImageView中src与background的区别
    Android见招拆招九:字符编码问题导入项目报错
    Android见招拆招八:多次遇到的R.java编译问题
    Android学习笔记五:(布局)Layout_margin和Layout_padding的区别
    Android见招拆招七:Error parsing XML: no element
    Window10系统修改hosts文件的方法
    Foxmail:‘错误信息:由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败’的解决办法
    Oracle 查询NULL字段/空字符串
    Python 安装第三方模块时 报Retrying(Retry(total=4, connect=None, read=None, redirect=None, status=None))...[WinError 10061]由于目标计算机积极拒绝,无法连接 错误
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4839499.html
Copyright © 2011-2022 走看看