左右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编码的字符串。不管那个函数,假设字符串包括中文,都须要进一步转化成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库的下载地址上文已经给出。

通过更改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中文乱码问题分析与解决”话题。就到此为止。希望能对大家有点帮助。

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

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

左右c++与java中国的垃圾问题的分析与解决的更多相关文章

  1. 文《左右c++与java中国的垃圾问题的分析与解决》一bug分析

    文<左右c++与java中国的垃圾问题的分析与解决>一bug分析 DionysosLai(906391500@qq.com) 2014/10/21 在前几篇一博客<关于c++与jav ...

  2. Java 虚拟机 - GC 垃圾回收机制分析

    Java 垃圾回收(Garbage Collection,GC) Java支持内存动态分配.垃圾自动回收,而 C++ 不支持.我想这可能也是 为什么 Java 脱胎于 C++ 的一个原因吧. GC 的 ...

  3. Java并发-ConcurrentModificationException原因源码分析与解决办法

    一.异常原因与异常源码分析 对集合(List.Set.Map)迭代时对其进行修改就会出现java.util.ConcurrentModificationException异常.这里以ArrayList ...

  4. (转)postfix疯狂外发垃圾邮件之分析与解决

    从进程中看到,好像是postfix有问题.我这postfix主要是用来给程序发达邮件用的,如报警,程序外发邮件等.平时postfix进程不会像现在这样异常,这在postf主进程CPU占用高,其它的相关 ...

  5. 在java中使用RBL服务器(中国反垃圾邮件联盟的CBL+使用)

    这是06年写的,不知道现在RBL改了没,不过恢复过来做记录,以后可能需要. 实时黑名单(RBL)实际上是一个可供查询的IP地址列表,通过DNS的查询方式来查找一个IP地址的A记录是否存在来判断其是否被 ...

  6. Java编程思想学习笔记_1(Java内存和垃圾回收)

    1.Java中对象的存储数据的地方: 共有五个不同的地方可以存储数据. 1)寄存器.最快,因为位于处理器的内部,寄存器按需求分配,不能直接控制. 2)堆栈.位于通用RAM,通过堆栈指针可以从处理器那里 ...

  7. Java虚拟机之垃圾回收详解一

    Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...

  8. struts2注解redirect传递参数解决方案时,中国的垃圾问题

    struts2注解redirect传递参数解决方案时,中国的垃圾问题 试过很多方法  tomcat 编码  .字符串转换 .URLEncoder  .. 但是,没有解决方案,然后仔细阅读   stru ...

  9. 【java虚拟机序列】java中的垃圾回收与内存分配策略

    在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...

随机推荐

  1. zookeeper错误KeeperErrorCode = ConnectionLoss解决

    原因: 一般是由于连接还未完成就执行zookeeper的get/create/exsit操作引起的. 解决方法: 利用"CountDownLatch 类 + zookeeper的watche ...

  2. statickeyword于C和C++用法

    一.C语言statickeyword两个使用 1).一个功能修改内部使用的变量,函数内的静态变量.这些变量的寿命比功能不再,它是具有一定的函数"状态",使用静态变量的作用通常是不可 ...

  3. 【Android笔记】MediaPlayer基本用法

    Android MediaPlayer基本使用方式 使用MediaPlayer播放音频或者视频的最简单样例: JAVA代码部分: public class MediaPlayerStudy exten ...

  4. 区域及分离、Js压缩、css、jquery扩展

    后台管理区域及分离.Js压缩.css.jquery扩展 本系列目录:ASP.NET MVC4入门到精通系列目录汇总 有好一段时间没更新博文了,最近在忙两件事:1.看书,学习中...2.为公司年会节目做 ...

  5. post跨域请求

    [名词解释] 跨域:https://developer.mozilla.org/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript 同源策略 ...

  6. Agile/CMMI/Scrum

    Agile/CMMI/Scrum 一.背景介绍 在朋友(aehyok)的建议下,初步去了解Visual Studio Online,简称VS Online(即原来的 Team Foundation S ...

  7. (转)mvn clean install 与 mvn install 的区别(为啥用clean)

    之前写代码的过程中曾经遇到过问题,用mvn install后,新改的内容不生效,一定要后来使用mvn clean install 才生效,由于之前没有做记录,以及记不清是什么情况下才会出现的问题,于是 ...

  8. java提高篇(十)-----强制类型转换

    在java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需 ...

  9. Javascript作用域问题的构造函数的变量

    构造函数new对于使用.代表创建对象.此外,它可以被用作普通的函数调用,因为它也是一个功能. function Person(name) { this.name=name; } Person(12); ...

  10. iOS开发:多线程技术概述

    一.概述 线程(thread):用于指代独立执行的代码段. 进程(process):用于指代一个正在运行的可执行程序,它可以包含多个线程. 任务(task):用于指代抽象的概念,表示需要执行工作. 多 ...