java 与jni转码_JNI 中文转码问题

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的,所以就目前大多数应用而言,转换仍然是必须的。

具体的转换函数,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意义不大,但是对整个系统还是必要的。

本人用了这个上面的方法进行了编码转换,在处理时候发现有两个问题:

1)对于大文本转换速度太慢,成了系统的瓶颈;

2)对于一些文本会出现乱码问题,应该是库中没有对应的字符造成的;

另外,可以通过简单的修改实现保证iconv在进行转化的时侯不会到中途因为不能转化而终止,具体的方法就是当遇到不能转化的字符时候让指针向前一个字符,更具体的代码网上有人贴了出来,可以搜索得到!

个人观点其实在非要用JNI调用C++处理大批量中文时候,最好在C++中留有一个接口,该接口接收一个文件名做为参数,然后让JAVA程序把要处理的中文文本以本地编码输入到文件中,然后让JNI把文件名传给C++,这样就可以免去编码转换问题!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java FFmpeg是一个基于Java开发的FFmpeg API,它允许开发人员使用Java来访问FFmpeg的功能和特性,从而能够很方便地实现音频/视频处理、转码等功能。 Java FFmpeg的优点在于它采用了Java语言的特性,如面向对象、异常处理、泛型等,使得开发者能够更加轻松的编写代码,并且避免了C语言中指针操作和内存管理等问题,提高了编写代码的效率和代码的可读性。 Java FFmpeg提供了丰富的API,可以处理音频、视频的编码、解码、格式转换、裁剪、合并等等,同时也非常容易集成到其它Java应用程序中,使得实现多媒体处理功能变得更加简单和便捷。 Java FFmpeg的使用限制在于它需要Java虚拟机(JVM),并且它对硬件资源的利用不如本地C/C++编写的FFmpeg,因此在处理大规模的音视频数据时,需要考虑JVM的资源约束。 总之,Java FFmpeg是一种优秀的,基于Java语言开发的FFmpeg API,可以方便地实现多媒体处理功能。 ### 回答2: Java ffmpeg是一种Java平台上使用ffmpeg进行视频和音频处理的框架和库。FFmpeg是一个开源的多媒体工具集,可以对音视频进行录制、编码、解码、合成、剪辑等处理。Java ffmpeg框架将ffmpeg集成到Java应用程序中,可以通过Java API来调用FFmpeg的功能,实现多媒体文件的转换、切割、剪辑、合并、压缩和解码等操作。Java ffmpeg框架对FFmpeg进行了包装,并提供了一系列便捷的API,使得开发者不需要深入学习FFmpeg的底层原理和命令行参数,就可以轻松地完成多媒体处理任务。同时,Java ffmpeg框架也提供了一些额外的功能,如实时流媒体传输、音视频的采集和处理等,可以应用于视频会议、实时直播、音视频监控等领域。在Java平台上使用ffmpeg进行音视频处理,Java ffmpeg是一个高效、可靠、易用的选择。 ### 回答3: Java FFmpeg是指基于Java开发的FFmpeg工具,它是一个跨平台的多媒体框架,可用于处理音频、视频和图像等格式的文件。Java FFmpeg可以读取、解码、编码、转换和播放音频和视频文件,还支持录制和实时视频流等功能。 Java FFmpeg的运行需要依赖FFmpeg本身,可以通过JNIJava Native Interface)来实现Java与FFmpeg的交互和调用。它提供了丰富的API和工具,包括命令行工具、Java接口和封装库等,使得开发者可以方便地使用它来完成各种音视频处理任务。 Java FFmpeg的应用可以广泛涵盖视频编辑、媒体处理、实时流媒体、视频转码和格式转换等领域。比如,在视频编辑中可以使用Java FFmpeg来对视频文件进行剪辑、混音、字幕添加等操作,在音视频实时转码和解码中,Java FFmpeg可以支持多种码流,提供高效的音视频数据处理能力。 总之,Java FFmpeg是一款具有高度可定制性和灵活性的音视频处理工具,它可以让开发者在Java环境下快速、高效地实现各种媒体处理需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值