关于c++与java中文乱码问题分析与解决

关于c++与java中文乱码问题分析与解决

DionysosLai([email protected])  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编码的字符串。无论那个函数,如果字符串包含中文,都需要进一步转化成C\C++的编码格式:GB2312。

C++->java数据传递

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

如果没有中文字符,就只有标准的ascii码值,那么使用GetStringUTFChars/NewStringUTF可以轻松搞定。因为在这种情况下,utf-8编码和ascii编码是一致,不需要转换。

如果存在中文字符,那么在C\C++部分进行编码就是必须的,一个是把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:\EngilshLogicGame\EnglishGame\cocos2d-x-2.2.3\cocos2dx\platform\third_party\win32,在这里面还包括其他的一些库文件,比方说网络库,解析png库等。引擎在Android平台,没有自带iconv库(个人猜测原因是由于ndk自带iconv库了,因此其实可以不用自己下载iconv库,但这里,我们给出方法是使用自己下载的iconv库),iconv库的下载地址上文已经给出。

通过更改工程proj.android/jni/Android.mk文件,将iconv库文件加载进Eclipse中。在mk文件中加入了下面两句话,如图所示:

注意:这里我将下载的iconv库文件放在了引擎的external文件下(当然,也可以发在别的地方,只需要更改对应的目录文件即可),如图所示:

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

更改方式,如图所示:

注意:画圈的两个关键字,与之前修改的proj.android/jni/Android.mk文件中的关键字是一致的。

到这里,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中文乱码问题分析与解决”话题,就到此为止,希望能对大家有点帮助。也感谢公司的同事给予的帮助,和网上的一些博主。

关于c++与java中文乱码问题分析与解决,布布扣,bubuko.com

时间: 2024-10-11 17:49:33

关于c++与java中文乱码问题分析与解决的相关文章

文《关于c++与java中文乱码问题分析与解决》中一个bug分析

文<关于c++与java中文乱码问题分析与解决>中一个bug分析 DionysosLai([email protected]) 2014/10/21 在前几篇一博客<关于c++与java中文乱码问题分析与解决>,地址如下:http://blog.csdn.net/dionysos_lai/article/details/38389765.文中详细介绍了c++与java数据传递时,为何会出现中文乱码的原因,并提出了适当的解决方法.方法如下: int CCDirector::GBKTo

关于Android与pc通信时中文乱码的分析和解决

初步实现了Android与pc服务器的通信之后,又碰到了传说中令人头疼不已的中文乱码问题.既然出现了乱码,那么原因自然是协议不通了.我们知道eclipse中默认的编码标准是GBK,而安卓程序开发所默认的布局文件编码标准则是utf-8,这样一来,我们双方通信的时候便难免出现乱码.要解决它,就要从二者转换方面着手.     首先我们知道,从安卓手机界面上获得的文字,其编码字符集是utf-8,所以,当我们的java文件获得它时,它是以utf-8形式编译的.所以这里,在得到EditText中的文字之后,

php中文乱码问题分析及解决办法

中文乱码问题产生的原因,主要就是字符编码设置问题: 首先,mysql数据库安装的时候字符编码要选择正确,最好选择utf-8比较保险.如果安装时没有设置正确,找到mysql的安装目录,修改my.conf配置文件中的字符设置,打开文件,应该一个是在mysqll下面,一个是在server下面的. 如果是php页面的中文乱码,也就是非数据库查询出来的数据,HTML页面静态的部分出现乱码,应该使用header("content-type:text/html; charset=utf8") 来设定

java中文乱码解决之道(一)-----认识字符集

沉寂了许久(大概有三个多月了吧),LZ"按捺不住"开始写博了! java编码中的中文问题是一个老生常谈的问题了,每次遇到中文乱码LZ要么是按照以前的经验修改,要么则是baidu.com来解决问题.阅读许多关于中文乱码的解决办法的博文后,发现对于该问题我们都(更加包括我自己)没有一个清晰明了的认识,于是LZ想通过这系列博文(估计只有几篇)来彻底分析.解决java中文乱码问题,如有错误之处望各位同仁指出!当然,此系列博文并非LZ完全原创,都是在前辈基础上总结,归纳,如果雷同纯属借鉴-- 问

中文乱码的分析 和 从Eclipse设置启动JVM时的字符集(转)

最近时常碰到中文乱码的问题,eclipse的编码环境设置的都是UTF-8,外部也是以UTF-8的编码进行传参的,但是遇到中文的时候还是因为乱码而产生一系列的错误.在网上查了许多资料,发现这是跟JVM的编码有关系的,JVM默认引用电脑操作系统的编码格式进行编码(大部分中文win xp系统的编码格式是GBK),所以JVM把java编译成class文件的时候会以GBK的方式进行编译.于是乎你会发现,有的机器运行工程会始终有乱码,有的机器则不会 获取JVM编码: import java.nio.char

java中文乱码解决方法汇总

publicstaticvoidmain(String[]argv){ try{ System.out.println("中文");//1 System.out.println("中文".getBytes());//2 System.out.println("中文".getBytes("GB2312″));//3 System.out.println("中文".getBytes("ISO8859_1″));

Java中文乱码处理

一.处理get方法中文乱码 方法1   String name = new String(request.getParameter("userName").getBytes("iso-8859-1")); 方法2   在tomcat的conf文件下server.xml中redirectPort="8443"位置后添加: URIencoding="GBK" 二.处理post方法中文乱码 request.setCharacte

java中文乱码解决之道(七)-----JSP页面编码过程

我们知道JSP页面是需要转换为servlet的,在转换过程中肯定是要进行编码的.在JSP转换为servlet过程中下面一段代码起到至关重要的作用. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="GBK" %> 在上面代码中有两个地方存在编码:pageEncoding.contentType的charset.其中pageEnco

java中文乱码解决之道(二)-----字符编码详解:基础知识 + ASCII + GB**

在上篇博文(java中文乱码解决之道(一)-----认识字符集)中,LZ简单介绍了主流的字符编码,对各种编码都是点到为止,以下LZ将详细阐述字符集.字符编码等基础知识和ASCII.GB的详情. 一.基础知识 在了解各种字符集之前我们需要了解一些最基础的知识,如:编码.字符.字符集.字符编码基础知识. 编码 计算机中存储的信息都是用二进制表示的,我们在屏幕上所看到文字.图片等都是通过二进制转换的结果.编码是信息从一种形式或格式转换为另一种形式的过程,通俗点讲就是就是将我们看到的文字.图片等信息按照