中字符转换中文乱码的处理方法
这两天在学习使用jni,在java程序中,调用海量词典的dll。利用jni的GetStringChars函数和NewString函数时,遇到了中文乱码的问题,折腾了一个晚上。查阅了一些资料,总结如下:
一.相关概念
java内部是使用16bit的unicode编码(UTF-16)来表示字符串的,无论中文英文都是2字节; jni内部是使用UTF-8编码来表示字符串的,UTF-8是变长编码的unicode,一般ascii字符是1字节,中文是3字节; c/c++使用的是原始数据,ascii就是一个字节了,中文一般是GB2312编码,用两个字节来表示一个汉字。
明确了概念,操作就比较清楚了。下面根据字符流的方向来分别说明一下
1、java --> c/c++
这种情况中,java调用的时候使用的是UTF-16编码的字符串,jvm把这个字符串传给jni,c/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)
2、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的,所以就目前大多数应用而言,转换仍然是必须的。
二。一种转换方法
使用wide char类型来转换。
char* jstringToWindows( JNIEnv *env, jstring jstr )
{ //UTF8/16转换成gb2312
int length = (env)->GetStringLength(jstr );
const jchar* jcstr = (env)->GetStringChars(jstr, 0 );
char* rtn = (char*)malloc( length*2+1 );
int size = 0;
size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
if( size <= 0 )
return NULL;
(env)->ReleaseStringChars(jstr, jcstr );
rtn[size] = 0;
return rtn;
}
jstring WindowsTojstring( JNIEnv* env, const char* str )
{//gb2312转换成utf8/16
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;
}
补充(需要包含的头文件):
/*包含*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <Windows.h>
http://hi.baidu.com/menghaisheng/blog/item/33e19cfc5a237354d6887d07.html
中字符转换中文乱码的处理方法相关推荐
- RStudio控制台(console)中出现少量中文乱码的解决方法
RStudio控制台(console)中出现少量中文乱码的解决方法 参考文章: (1)RStudio控制台(console)中出现少量中文乱码的解决方法 (2)https://www.cnblogs. ...
- c++中关于SQLite中文乱码的解决方法
在使用SQLite的过程中(c++),如果创建一个表,如果SQL语句中包含中文字符,就会报错:如果是从数据库表中查询数据,如果数据库表中的某些字段为中文,查询结果也不能正常显示,出现这种情况的原因是因 ...
- ASP中 Request.Form中文乱码的解决方法
分享下解决方法 直接用request.Form()获取的是所有数据所以会有乱码(具体原因不祥) 用 VBScript code Foreachobj in Request.Form Response. ...
- java 转换gbk编码,java中GBK转UTF-8乱码的解决方法
java中GBK转UTF-8乱码的解决方法 如果自己采用的是GBK编码,对方采用得到是UTF-8编码,发送数据时需要将GBK编码数据转换成UTF-8编码数据,这样对方才不会乱码. 问题出现:GBK转U ...
- 【转】QT中使用MYSQL中文乱码解决方法
[转]QT中使用MYSQL中文乱码解决方法 Linux下乱码解决办法: 1.在QT程序的main.cpp的main函数中添加红色字那三句: int main(int argc, char *argv[ ...
- ftl转PDF服务器上中文不显示,解决Linux中swftools转换中文pdf时出现乱码问题
前段时间安装了swftools可以将pdf转换为swf文件,然后配合一个FlexPaper,就可以做成和百度图文库类似的东东了. 但是今天,我们开发的同事告诉我说pwd转换的这个会有乱码问题,我看了一 ...
- linux mysql 乱码怎么解决_MySQL_linux中解决mysql中文乱码方法,改默认编码:/etc/init.d/my - phpStudy...
linux中解决mysql中文乱码方法 改默认编码: /etc/init.d/mysql start (stop) 为启动和停止服务器 /etc/mysql/ 主要配置文件所在位置 my.cnf /v ...
- linux中mysql不显示中文_linux中解决mysql中文乱码方法
改默认编码: /etc/init.d/mysql start (stop) 为启动和停止服务器 /etc/mysql/ 主要配置文件所在位置 my.cnf /var/lib/mysql/ 放置的是数据 ...
- Activiti保存.png 流程图片文件且解决idea中保存图片时显示中文乱码的解决方法
Activiti保存.png 流程图片文件且解决idea中保存图片时显示中文乱码的解决方法 Eclipse 工具中的操作 流程图片生成的两种方式: 使用 activiti-designer 设计流程图 ...
最新文章
- 60颗卫星被五手火箭送上天!马斯克疯狂的卫星互联网计划不远了
- Spring实战之二:装配Bean
- MacOS中安装python-jekins失败解决方法
- 思考:Linux Kernel的中断处理函数中是否会被其它程序(中断/异常)打断?
- 第24天学习Java的笔记-接口Interface
- 【CV】ECCV2020图像分割开源论文合集
- Integer 中的缓存类IntegerCache
- SLF4J简介与使用(整合log4j)
- idea2019打卡没多久就闪退_IDEA 2020.1打开时闪退的问题及解决方法(完美解决方法)...
- TypeError: to_categorical() got an unexpected keyword argument 'nb_classes'
- 华为2022校园赛——车道渲染
- 【Word】利用域代码快速实现自定义编号
- ARM-linux开发板网线连接电脑访问外网
- 第九届河南省程序设计大赛 1273-宣传墙(java)
- 可视化拖拽组件库一些技术要点原理分析(三)
- 一图掌握ISACA五大资格证书体系
- RCNN,Fast RCNN, Faster RCN解析
- Nginx学习心得总结第一章
- 【考研】2022暨南大学848 电子信息(计算机技术) 经验贴 经验贴汇总
- k线顶分型 python_K线的顶分型与底分型(实例图解)
热门文章
- 安装vmtools之后任然不能在虚拟机和主机之间复制粘贴的问题
- java中final,static,this,supper关键字的异同
- video标签 设置背景图片
- mbp2015 款发热主因
- 用python画微信表情_【一点资讯】“裂开了,苦涩了,翻白眼”!我用Python画出微信新出的表情包 www.yidianzixun.com...
- 数据结构期末考试复习整理
- 3.5Bootstrap组件篇之导航条
- dr.fone for android,Wondershare Dr.Fone for Android
- skywalking获取traceId(tid)的方式
- 读后感----《我奋斗了18年才和你坐在一起喝咖啡》