Конвертировать байт ICU4C в символ java - PullRequest
1 голос
/ 22 февраля 2011

Я обращаюсь к функции ICU4C через JNI, которая возвращает UChar * (т.е. массив символов Unicode) .... Я смог преобразовать это в jbyteArray, приравнивая каждый член массива UChar к локальному массиву jbyte [], который Я создал, а затем вернул его в Java с помощью функции env-> SetByteArrayRegion () ... теперь у меня есть массив Byte [] в Java, но все это довольно бессмысленно ... В лучшем случае странные символы ... Я не уверен где проблема может быть ... Я работаю с символами Юникода, если это имеет значение ... как мне правильно преобразовать байт [] в символ [] в Java? Что-то не правильно отображается ... Вот фрагмент кода:


--- 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 (новая строка (myICUBytes, Charset.forName ("UTF-16"))), и это так же, как и gebberishy ....

обратите внимание, что функция ICU возвращает правильные символы Юникода в UChar * ... где-то между преобразованием в jbyteArray и Java, которое не работает ...

Помощь!

Ответы [ 2 ]

1 голос
/ 23 февраля 2011
destChr[i] = testStr[i];   //is this correct?

Это похоже на проблему.

JNI-типы :

byte   jbyte    signed 8 bits
char   jchar    unsigned 16 bits

Типы ICU4C :

Определите UChar как wchar_t, если это 16 бит шириной; всегда предполагается, что без знака.

Если ширина wchar_t не равна 16 битам, то определить UChar как uint16_t или char16_t потому что GCC> = 4.4 может обрабатывать UTF16 строковые литералы. Это делает определение платформы UChar зависит от платформы но допускает прямой тип строки совместимость с платформами с 16-битные типы wchar_t.

Итак, помимо всего, что может делать icu_function, вы пытаетесь вписать 16-битное значение в тип 8-битной ширины.

Если вам необходимо использовать байтовый массив Java, я предлагаю преобразовать его в 8-битный тип char путем транскодирования в кодировку Unicode.

Перефразируя код 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 ++ соответствующим образом.

0 голосов
/ 22 февраля 2011

Рассматривали ли вы использование ICU4J?

Кроме того, при преобразовании ваших байтов в строку вам нужно будет указать кодировку символов. Я не знаком с рассматриваемой библиотекой, поэтому не могу дать вам дальнейших советов, но, возможно, это будет "UTF-16" или подобное?

О, и также стоит отметить, что вы можете просто получать ошибки отображения, потому что терминал, на который вы печатаете, не использует правильный набор символов и / или не имеет правильных доступных символов.

...