我再一次搞乱java natve界面,我遇到了另一个有趣的问题。我通过jni向c发送文件路径,然后进行一些I / O.所以我遇到的最常见的问题是'äåö'。以下是具有完全相同问题的程序的简短演示:
爪哇:
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
这是 NOT 我想要的结果,我希望它输出与java中相同的字符串。
答案 0 :(得分:3)
您正在处理特定于平台的字符编码问题。虽然标准的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终止符,但它太长了。