Как мне конвертировать jstring в wchar_t *
Допустим, что на стороне C++ моя функция принимает переменную типа jstring
названный myString
, Я могу преобразовать его в строку ANSI следующим образом:
const char* ansiString = env->GetStringUTFChars(myString, 0);
есть ли способ получить
const wchar_t* unicodeString =
...
9 ответов
Если это кому-то поможет... Я использовал эту функцию для проекта 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;
}
JNI также имеет функцию GetStringChars(). Тип возвращаемого значения - const jchar*, jchar - 16-битный на win32, поэтому он будет совместим с wchar_t. Не уверен, что это настоящий UTF-16 или что-то еще...
А кто освобождает 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;
}
Я знаю, что об этом спрашивали год назад, но мне не нравятся другие ответы, поэтому я все равно отвечу. Вот как мы это делаем в нашем источнике:
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;
}
РЕДАКТИРОВАТЬ: Это решение хорошо работает на платформах, где wchar_t составляет 2 байта, некоторые платформы имеют 4 байта wchar_t, и в этом случае это решение не будет работать.
Портативное и надежное решение - использовать iconv, понимая, что вы должны знать, какую кодировку использует ваша система. wchar_t
использует (например, UTF-16 в Windows, UTF-32 во многих системах Unix).
Если вы хотите свести к минимуму свою зависимость от стороннего кода, вы также можете прокрутить свой собственный конвертер UTF-8. Это легко, если конвертировать в UTF-32, несколько сложнее с UTF-16, потому что вам приходится работать и с суррогатными парами.:-P Кроме того, вы должны быть осторожны, чтобы отклонить не самые короткие формы, иначе в некоторых случаях это может привести к появлению ошибок безопасности.
Если мы не заинтересованы в кроссплатформенности, в окнах вы можете использовать функцию MultiByteToWideChar или полезные макросы A2W (см. Пример).
Вот как я преобразовал jstring
к LPWSTR
.
const char* nativeString = env->GetStringUTFChars(javaString, 0);
size_t size = strlen(nativeString) + 1;
LPWSTR lpwstr = new wchar_t[size];
size_t outSize;
mbstowcs_s(&outSize, lpwstr, size, nativeString, size - 1);
Я пытаюсь jstring->char->wchar_t
char* js2c(JNIEnv* env, jstring jstr)
{
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0)
{
rtn = (char*)malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
jstring c2js(JNIEnv* env, const char* str) {
jstring rtn = 0;
int slen = strlen(str);
unsigned short * buffer = 0;
if (slen == 0)
rtn = (env)->NewStringUTF(str);
else {
int length = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)str, slen, NULL, 0);
buffer = (unsigned short *)malloc(length * 2 + 1);
if (MultiByteToWideChar(CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length) > 0)
rtn = (env)->NewString((jchar*)buffer, length);
free(buffer);
}
return rtn;
}
jstring w2js(JNIEnv *env, wchar_t *src)
{
size_t len = wcslen(src) + 1;
size_t converted = 0;
char *dest;
dest = (char*)malloc(len * sizeof(char));
wcstombs_s(&converted, dest, len, src, _TRUNCATE);
jstring dst = c2js(env, dest);
return dst;
}
wchar_t *js2w(JNIEnv *env, jstring src) {
char *dest = js2c(env, src);
size_t len = strlen(dest) + 1;
size_t converted = 0;
wchar_t *dst;
dst = (wchar_t*)malloc(len * sizeof(wchar_t));
mbstowcs_s(&converted, dst, len, dest, _TRUNCATE);
return dst;
}
Скорее просто. Но не забудьте освободить память с помощью 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);
}
Просто используйте env->GetStringChars(myString, 0); Java передать Unicode по своей природе