gpt4 book ai didi

Java JNI : Passing multibyte characters from java to c

转载 作者:太空宇宙 更新时间:2023-11-04 07:20:10 25 4
gpt4 key购买 nike

我又一次在 java natve 接口(interface)上胡思乱想,遇到了另一个有趣的问题。我正在通过 jni 将文件路径发送到 c,然后执行一些 I/O。所以我遇到的最常见的字符是 'äåö'。这是一个具有完全相同问题的程序的简短演示:

Java:

public class java {

private static native void printBytes(String text);
static{
System.loadLibrary("dll");
}

public static void main(String[] args){
printBytes("C:/Users/ä-å-ö/Documents/Bla.txt");
}
}

C:

#include "java.h"
#include <jni.h>

JNIEXPORT void JNICALL Java_java_printBytes(JNIEnv *env, jclass class, jstring text){
const jbyte* text_input = (*env)->GetStringUTFChars(env, text, 0);
jsize size = (*env)->GetStringUTFLength(env, text);
int i = 0;
printf("%s\n",text_input);
(*env)->ReleaseStringUTFChars(env, text, text_input);
}

输出:C:/Users/├ñ-├Ñ-├Â/Documents/Bla.txt

不是我想要的结果,我希望它输出与 java 中相同的字符串。

最佳答案

您正在处理特定于平台的字符编码问题。虽然标准的 c printf 应该能够处理多字节 (utf-8) 编码的字符串,但 windows/msvc 提供的不是标准的,也不能。在非 Windows 标准兼容平台上,您的代码会正常工作。来自 java 的字符串采用 UTF-8(多字节字符)格式,而 MS printf 需要 ASCII(每个字符一个字节)。这适用于 ASCII 字符,因为在 UTF-8 中这些字符具有相同的值。它不适用于 ASCII 以外的字符。

基本上,您需要将字符串转换为宽字符 (text.getBytes(Charset.forName(UTF-16LE"))) 并将其作为数组从 java 传递到 c 或将多字节字符串接收后在c中转为宽字符(MultiByteToWideChar(CP_UTF8, ...)),然后可以使用printf("%S") 或wprintf("%s") 输出.

参见 Printing UTF-8 strings with printf - wide vs. multibyte string literals了解更多信息。另请注意,答案说如果您想在 Windows 控制台上输出 unicode,则必须使用 _setmode 设置 unicode 输出模式。

另请注意,我不相信 GetStringUTFLength 保证 NUL 终止符,但它已经太长了。

关于Java JNI : Passing multibyte characters from java to c,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22054617/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com