2008-09-15 4 views
12

Предположим, что на стороне C++ моя функция принимает переменную типа jstring с именем myString. Я могу преобразовать его в строку ANSI следующим образом:Как преобразовать jstring в wchar_t *

const char* ansiString = env->GetStringUTFChars(myString, 0); 

есть способ получения

const wchar_t* unicodeString = ...

ответ

3

Портативное и надежное решение заключается в использовании iconv, с пониманием того, что вы должны знать, что кодирует ваша система wchar_t (например, UTF-16 для Windows, UTF-32 для многих Unix-систем).

Если вы хотите свести к минимуму зависимость от стороннего кода, вы также можете вручную конвертировать собственный конвертер UTF-8. Это легко сделать, если преобразовать в UTF-32, несколько сложнее с UTF-16, потому что вам придется обрабатывать суррогатные пары тоже. :-P Кроме того, вы должны быть осторожны, чтобы отклонить формы non-shortest, или в некоторых случаях могут открывать ошибки безопасности.

+0

Вы предлагаете преобразовать jstring в UTF-8, затем обратно в UTF-16? Это действительно необходимо? – Rup 2012-01-05 13:01:32

+0

@Rup jstrings уже являются UTF-8: «JNI использует модифицированные строки UTF-8 для представления различных типов строк. Модифицированные строки UTF-8 такие же, как и те, которые используются виртуальной машиной Java. Модифицированные строки UTF-8 закодированы так, что символьные последовательности, содержащие только ненулевые символы ASCII, могут быть представлены с использованием только одного байта на символ, но все символы Unicode могут быть представлены ..... Виртуальная машина Java не распознает четырехбайтовый формат стандартного UTF-8; вместо этого использует свой собственный двух-трехбайтовый формат ». – 2012-05-23 17:36:27

+0

@ b1naryatr0phy Действительно? jni.h на моей системе (оба 1.6 и 1.7) имеет «typedef unsigned short jchar», который больше похож на UTF-16. – Rup 2012-05-24 00:08:25

0

Если нас не интересует возможность перекрестной платформы, в окнах вы можете использовать функцию MultiByteToWideChar или полезные макросы A2W (ссылка example).

3

JNI также имеет функцию GetStringChars(). Тип возврата - const jchar *, jchar - 16 бит в win32, поэтому он будет совместим с wchar_t. Не уверен, что это реальный UTF-16 или что-то еще ...

+0

Вы случайно не знаете, совместим ли порядок байтов jchar с Win32 wchar_t? Это должно быть, но, вероятно, хорошо быть уверенным. :-) – 2008-09-16 02:13:25

0

Просто используйте env-> GetStringChars (myString, 0); Java pass Unicode по своей природе

2

Я знаю, что это было задано год назад, но мне не нравятся другие ответы, поэтому я все равно отвечу. Вот как мы это делаем в нашем источнике:

wchar_t * JavaToWSZ(JNIEnv* env, jstring string) 
{ 
    if (string == NULL) 
     return NULL; 
    int len = env->GetStringLength(string); 
    const jchar* raw = env->GetStringChars(string, NULL); 
    if (raw == NULL) 
     return NULL; 

    wchar_t* wsz = new wchar_t[len+1]; 
    memcpy(wsz, raw, len*2); 
    wsz[len] = 0; 

    env->ReleaseStringChars(string, raw); 

    return wsz; 
} 

EDIT: Это решение хорошо работает на платформах, где wchar_t 2 байта, некоторые платформы имеют 4 байтовый wchar_t в этом случае это решение не будет работать.

4

И кто освобождает wsz? Я бы порекомендовал STL!

std::wstring JavaToWSZ(JNIEnv* env, jstring string) 
{ 
    std::wstring value; 
    if (string == NULL) { 
     return value; // empty string 
    } 
    const jchar* raw = env->GetStringChars(string, NULL); 
    if (raw != NULL) { 
     jsize len = env->GetStringLength(string); 
     value.assign(raw, len); 
     env->ReleaseStringChars(string, raw); 
    } 
    return value; 
} 
0

Скорее простой. Но не забудьте, чтобы освободить память на ReleaseStringChars

JNIEXPORT jboolean JNICALL Java_TestClass_test(JNIEnv * env, jobject, jstring string) 
{ 
    const wchar_t * utf16 = (wchar_t *)env->GetStringChars(string, NULL); 
    ... 
    env->ReleaseStringChars(string, utf16); 
} 
13

Если это поможет кому-то ... Я использовал эту функцию для Android проекта:

std::wstring Java_To_WStr(JNIEnv *env, jstring string) 
{ 
    std::wstring value; 

    const jchar *raw = env->GetStringChars(string, 0); 
    jsize len = env->GetStringLength(string); 
    const jchar *temp = raw; 
    while (len > 0) 
    { 
     value += *(temp++); 
     len--; 
    } 
    env->ReleaseStringChars(string, raw); 

    return value; 
} 

Улучшенное решение может быть (спасибо за обратная связь):

std::wstring Java_To_WStr(JNIEnv *env, jstring string) 
{ 
    std::wstring value; 

    const jchar *raw = env->GetStringChars(string, 0); 
    jsize len = env->GetStringLength(string); 

    value.assign(raw, raw + len); 

    env->ReleaseStringChars(string, raw); 

    return value; 
} 
Смежные вопросы