我通过JNI访问ICU4C函数,它返回一个UChar *(即unicode字符数组)....我能够通过将UChar数组的每个成员等同于本地jbyte []数组将其转换为jbyteArray我创建然后使用env-> SetByteArrayRegion()函数将其返回到Java ...现在我在Java中使用了Byte []数组但是它几乎都是乱码...奇怪的符号充其量......我不是确定问题可能在哪里...我正在使用unicode字符,如果这很重要...我如何正确地将byte []转换为java中的char []?有些东西没有正确映射......以下是代码片段:
--- JNI代码(改为更轻,使其更短)---
static jint testFunction(JNIEnv* env, jclass c, jcharArray srcArray, jbyteArray destArray) {
jchar* src = env->GetCharArrayElements(srcArray, NULL);
int n = env->getArrayLength(srcArray);
UChar *testStr = new UChar[n];
jbyte destChr[n];
//calling ICU4C function here
icu_function (src, testStr); //takes source characters and returns UChar*
for (int i=0; i<n; i++)
destChr[i] = testStr[i]; //is this correct?
delete testStr;
env->SetByteArrayRegion(destArray, 0, n, destChr);
env->ReleaseCharArrayElements(srcArray, src, JNI_ABORT);
return (n); //anything for now
}
- Java代码 - string wohoo =“ABCD bal bla bla”; char [] myChars = wohoo.toCharArray();
byte[] myICUBytes = new byte[myChars.length];
int value = MyClass.testFunction (myChars, myICUBytes);
System.out.println(new String(myICUBytes)) ;// produces gibberish & weird symbols
我也尝试过:System.out.println(new String(myICUBytes,Charset.forName(“UTF-16”))),它就像gebberishy一样....
请注意,ICU函数确实在UChar *中返回正确的unicode字符...转换为jbyteArray和Java之间的某些方面正在搞乱...
帮助!
答案 0 :(得分:1)
destChr[i] = testStr[i]; //is this correct?
这看起来像是一个问题。
byte jbyte signed 8 bits
char jchar unsigned 16 bits
如果是,则将UChar定义为wchar_t 16位宽;总是假设是 无符号的。
如果wchar_t不是16位宽,那么 将UChar定义为uint16_t或 char16_t因为GCC&gt; = 4.4可以处理 UTF16字符串文字。这使得 UChar平台依赖的定义 但允许直接字符串类型 与平台的兼容性 16位wchar_t类型。
因此,除了icu_function
可能正在做的任何事情之外,你试图将一个16位值装入一个8位宽的类型。
如果必须使用Java字节数组,我建议通过转码为Unicode编码来转换为8位char
类型。
解释some C code:
UChar *utf16 = (UChar*) malloc(len16 * sizeof(UChar));
//TODO: fill data
// convert to UTF-8
UConverter *encoding = ucnv_open("UTF-8", &status);
int len8 = ucnv_fromUChars(encoding, NULL, 0, utf16, len16, &status);
char *utf8 = (char*) malloc(len8 * sizeof(char));
ucnv_fromUChars(encoding, utf8, len8, utf16, len16, &status);
ucnv_close(encoding);
//TODO: char to jbyte
然后,您可以使用new String(myICUBytes, "UTF-8")
将其转码为Java字符串。
我使用的是UTF-8,因为它已经在我的示例代码中,您不必担心字节序。根据需要将我的C转换为C ++。
答案 1 :(得分:0)
你考虑过使用ICU4J吗?
此外,将字节转换为字符串时,您需要指定字符编码。我对这个图书馆不熟悉,所以我不能进一步建议你,但也许这将是“UTF-16”或类似的?
哦,还有值得注意的是,您可能只是因为您正在打印的终端没有使用正确的字符集和/或没有正确的字形而可能只是显示错误。