将ICU4C字节转换为java char

时间:2011-02-22 19:24:18

标签: java unicode java-native-interface icu

我通过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之间的某些方面正在搞乱...

帮助!

2 个答案:

答案 0 :(得分:1)

destChr[i] = testStr[i];   //is this correct?

这看起来像是一个问题。

JNI types

byte   jbyte    signed 8 bits
char   jchar    unsigned 16 bits

ICU4C types

  

如果是,则将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”或类似的?

哦,还有值得注意的是,您可能只是因为您正在打印的终端没有使用正确的字符集和/或没有正确的字形而可能只是显示错误。