如何使用JNI将java字符串转换为宽字符串

时间:2013-01-14 14:22:43

标签: java-native-interface unicode-string widechar

几个月前,我编写了一个使用JNI来封装C API的Java API。 C API使用char字符串,我使用GetStringUTFChars从Java字符串创建C字符串。

我忽略了思考非ASCII字符可能出现的问题。

从那时起,C API的创建者为每个需要或返回wchar_t字符串的C函数创建了宽字符等价物。我想更新我的Java API以使用这些宽字符函数,并克服我对非ASCII字符的问题。

研究过JNI文档之后,我对使用GetStringChars或GetStringRegion方法的相对优点感到有些困惑。

我知道wchar_t字符的大小因Windows和Linux而异,并且不确定创建C字符串的最有效方法(之后将它们转换回Java字符串)。

这是我目前的代码,我认为每个字符创建一个包含两个字节的字符串:

int len;
jchar *Src;

len = (*env)->GetStringLength(env, jSrc);
printf("Length of jSrc is %d\n", len);

Src = (jchar *)malloc((len + 1)*sizeof(jchar));
(*env)->GetStringRegion(env, jSrc, 0, len, Src);
Src[len] = '\0';

但是,当wchar_t的大小与jchar不同时,需要进行修改。

1 个答案:

答案 0 :(得分:1)

C API创建者是不是愿意退一步并重新实现 UTF-8 ? :)你的工作必然会消失,只需要GetStringUTFChars / NewStringUTF

jchar的类型定义为unsigned short,相当于 UTF-16 的JVM char。因此,在wchar_t为2字节 UTF-16 的Windows上,您可以取消您提供的代码。只需复制原始字节,相应地进行分配。完成C API调用后,不要忘记释放。与NewString补充以转换回jstring。

我所知道的唯一其他wchar_t大小是4字节(最突出的是Linux) UTF-32 。问题出在这里: UTF-32不仅仅是UTF-16以某种方式填充到4个字节。分配双倍的内存量只是一个开始。有一个实质性的转换,like this one which seems to be sufficiently free

但是如果你没有那么多表现并且愿意放弃在Windows上的普通内存复制,我建议将jstring转到UTF-8(这是JNI本身提供的文档化功能)然后UTF-8到UTF-16或UTF-32取决于sizeof(wchar_t)。关于每个平台给出的字节顺序和UTF编码,不会有任何假设。你好像在乎它,我发现你正在检查sizeof(jchar),对于大部分可见宇宙来说,它是2:)