【问题标题】:How to convert java strings to wide character strings using JNI如何使用 JNI 将 java 字符串转换为宽字符串
【发布时间】:2012-12-28 12:26:46
【问题描述】:

几个月前,我编写了一个使用 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 不同时,这将需要修改。

【问题讨论】:

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


    【解决方案1】:

    C API 创建者是否愿意退后一步,用 UTF-8 重新实现? :) 你的工作基本上会消失,只需要GetStringUTFChars/NewStringUTF

    jchar 的类型定义为 unsigned short,相当于 JVM char,即 UTF-16。因此,在 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 :)

    【讨论】:

    • 感谢@pavel 的回答——当然值得深思。当您说“您可以取消您提供的代码”时,我认为我的代码只是在复制原始字节(除了添加空终止符之外?我还能怎么做?也感谢 Unicode 转换链接和信息,因为那是我的下一个问题!(我试图投票给你的答案,但我不值得)
    • 在英特尔 Windows 的特定组合中,您可以真正避免复制原始字节,因为两种情况下的存储都是 UTF-16LE。如果 JVM 在 BE 架构上运行(罕见但可能),那么您将不得不添加一些字节交换。 “其他”解决方案不假设任何内容,而是使用 JNI 通过与字节顺序无关的 UTF-8 进行转换。
    • 当你被标记为有价值的时候回来,没问题:)
    • 好吧,我已经与编写 C API 的数据库供应商进行了进一步讨论,我们已同意恢复使用 UTF-8 函数,因此再次感谢您的建议。
    • 哇,你必须与数据库供应商有认真的关系:) 通常,可怜的 JNI 程序员会解决 C API 的缺陷,反之亦然。很高兴看到这个决议。
    猜你喜欢
    • 1970-01-01
    • 2011-10-05
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 2019-05-10
    • 2023-03-17
    • 2016-04-21
    相关资源
    最近更新 更多