1

我正在通过 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 代码 -- 字符串 woohoo = "ABCD bal bla bla"; char[] myChars = woohoo.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"))) 和它一样乱七八糟....

请注意,ICU 函数确实在 UChar *... 中返回正确的 unicode 字符,介于转换为 jbyteArray 和正在搞砸的 Java 之间...

帮助!

4

2 回答 2

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

这看起来像一个问题。

JNI 类型

byte   jbyte    signed 8 bits
char   jchar    unsigned 16 bits

ICU4C 类型

如果 UChar 为 16 位宽,则将 UChar 定义为 wchar_t;始终假定为无符号。

如果 wchar_t 不是 16 位宽,则将 UChar 定义为 uint16_t 或 char16_t,因为 GCC >=4.4 可以处理 UTF16 字符串文字。这使得 UChar 的定义依赖于平台,但允许直接字符串类型与具有 16 位 wchar_t 类型的平台兼容。

因此,除了icu_function可能做的任何事情之外,您还试图将 16 位值适合 8 位宽的类型。

如果必须使用 Java 字节数组,我建议char通过转码为 Unicode 编码来转换为 8 位类型。

套用一些 C 代码

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

然后,您可以使用 将其转码为 Java 字符串new String(myICUBytes, "UTF-8")

我使用 UTF-8 是因为它已经在我的示例代码中,您不必担心字节顺序。根据需要将我的 C 转换为 C++。

于 2011-02-22T21:40:09.727 回答
0

您是否考虑过使用 ICU4J?

此外,将字节转换为字符串时,您需要指定字符编码。我不熟悉有问题的库,所以我无法进一步建议您,但也许这将是“UTF-16”或类似的?

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

于 2011-02-22T19:28:32.107 回答