jstring(JNI) 到 std::string(c++) with utf8 字符
jstring(JNI) to std::string(c++) with utf8 characters
如何将 jstring
(JNI) 转换为具有 utf8
个字符的 std::string
(c++)?
这是我的代码。它适用于非 utf8 字符,但它对 utf8 字符是错误的。
std::string jstring2string(JNIEnv *env, jstring jStr){
const char *cstr = env->GetStringUTFChars(jStr, NULL);
std::string str = std::string(cstr);
env->ReleaseStringUTFChars(jStr, str);
return str;
}
经过很多时间才找到解决办法。我找到了一个方法:
在java中,一个unicode字符将使用2个字节(utf16
)进行编码。所以 jstring
将容器字符 utf16
。 std::string
在 C++ 中本质上是一个字节串,而不是字符,所以如果我们想将 jstring
从 JNI
传递到 c++
,我们必须将 utf16
转换为字节。
在文档 JNI functions 中,我们有 2 个函数从 jstring 中获取字符串:
// Returns a pointer to the array of Unicode characters of the string.
// This pointer is valid until ReleaseStringchars() is called.
const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);
// Returns a pointer to an array of bytes representing the string
// in modified UTF-8 encoding. This array is valid until it is released
// by ReleaseStringUTFChars().
const char * GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy);
GetStringUTFChars
,它会return一个modified utf8。
GetStringChars
会returnjbyte*,我们会从jbytes中读取char码,在c++中转成char
这是我的解决方案(适用于 ascii
和 utf8
字符):
std::string jstring2string(JNIEnv *env, jstring jStr) {
if (!jStr)
return "";
const jclass stringClass = env->GetObjectClass(jStr);
const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8"));
size_t length = (size_t) env->GetArrayLength(stringJbytes);
jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
std::string ret = std::string((char *)pBytes, length);
env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
env->DeleteLocalRef(stringJbytes);
env->DeleteLocalRef(stringClass);
return ret;
}
jboolean isCopy;
const char *convertedValue = (env)->GetStringUTFChars(yourJStringParam, &isCopy);
std::string string = std::string(convertedValue, length)
这很好用。试一试。
解释在这里:
http://www.club.cc.cmu.edu/~cmccabe/blog_jni_flaws.html
https://developer.android.com/training/articles/perf-jni(地区电话)
jsize
string_j2c(JNIEnv *env, jstring p, char *buffer) {
if (buffer != NULL) {
// Returns the length (the count of Unicode characters) of a
// Java string.
const jsize len = (*env).GetStringLength(p);
// Translates 'len' number of Unicode characters into modified
// UTF-8 encoding and place the result in the given buffer.
(*env).GetStringUTFRegion(p, 0, len, buffer);
// Returns JNI_TRUE when there is a pending exception;
// otherwise, returns JNI_FALSE.
const jboolean is_error = (*env).ExceptionCheck();
if (is_error == JNI_TRUE) {
return -1;
}
}
// Returns the length in bytes of the modified UTF-8
// representation of a string.
const jsize len = (*env).GetStringUTFLength(p);
return len;
}
const jsize len = string_j2c(env, p, NULL);
char buffer[len];
const jsize ret = string_j2c(env, p, buffer);
if (ret == -1) { // error
}
else {
__android_log_print(ANDROID_LOG_DEBUG, "Native", "%s", buffer);
}
我调整了 的答案,使其看起来像这样:
jboolean isCopy;
const char *convertedValue = (env)->GetStringUTFChars(yourJStringParam, &isCopy);
std::string str = convertedValue;
成功了!因为在标准 C++ 中,字符串文字的类型是 const char *
,因此您可以将 const char *convertedValue
分配给 std::string
.
类型的变量
如何将 jstring
(JNI) 转换为具有 utf8
个字符的 std::string
(c++)?
这是我的代码。它适用于非 utf8 字符,但它对 utf8 字符是错误的。
std::string jstring2string(JNIEnv *env, jstring jStr){
const char *cstr = env->GetStringUTFChars(jStr, NULL);
std::string str = std::string(cstr);
env->ReleaseStringUTFChars(jStr, str);
return str;
}
经过很多时间才找到解决办法。我找到了一个方法:
在java中,一个unicode字符将使用2个字节(utf16
)进行编码。所以 jstring
将容器字符 utf16
。 std::string
在 C++ 中本质上是一个字节串,而不是字符,所以如果我们想将 jstring
从 JNI
传递到 c++
,我们必须将 utf16
转换为字节。
在文档 JNI functions 中,我们有 2 个函数从 jstring 中获取字符串:
// Returns a pointer to the array of Unicode characters of the string.
// This pointer is valid until ReleaseStringchars() is called.
const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);
// Returns a pointer to an array of bytes representing the string
// in modified UTF-8 encoding. This array is valid until it is released
// by ReleaseStringUTFChars().
const char * GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy);
GetStringUTFChars
,它会return一个modified utf8。
GetStringChars
会returnjbyte*,我们会从jbytes中读取char码,在c++中转成char
这是我的解决方案(适用于 ascii
和 utf8
字符):
std::string jstring2string(JNIEnv *env, jstring jStr) {
if (!jStr)
return "";
const jclass stringClass = env->GetObjectClass(jStr);
const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8"));
size_t length = (size_t) env->GetArrayLength(stringJbytes);
jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
std::string ret = std::string((char *)pBytes, length);
env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
env->DeleteLocalRef(stringJbytes);
env->DeleteLocalRef(stringClass);
return ret;
}
jboolean isCopy;
const char *convertedValue = (env)->GetStringUTFChars(yourJStringParam, &isCopy);
std::string string = std::string(convertedValue, length)
这很好用。试一试。
解释在这里:
http://www.club.cc.cmu.edu/~cmccabe/blog_jni_flaws.html https://developer.android.com/training/articles/perf-jni(地区电话)
jsize
string_j2c(JNIEnv *env, jstring p, char *buffer) {
if (buffer != NULL) {
// Returns the length (the count of Unicode characters) of a
// Java string.
const jsize len = (*env).GetStringLength(p);
// Translates 'len' number of Unicode characters into modified
// UTF-8 encoding and place the result in the given buffer.
(*env).GetStringUTFRegion(p, 0, len, buffer);
// Returns JNI_TRUE when there is a pending exception;
// otherwise, returns JNI_FALSE.
const jboolean is_error = (*env).ExceptionCheck();
if (is_error == JNI_TRUE) {
return -1;
}
}
// Returns the length in bytes of the modified UTF-8
// representation of a string.
const jsize len = (*env).GetStringUTFLength(p);
return len;
}
const jsize len = string_j2c(env, p, NULL);
char buffer[len];
const jsize ret = string_j2c(env, p, buffer);
if (ret == -1) { // error
}
else {
__android_log_print(ANDROID_LOG_DEBUG, "Native", "%s", buffer);
}
我调整了
jboolean isCopy;
const char *convertedValue = (env)->GetStringUTFChars(yourJStringParam, &isCopy);
std::string str = convertedValue;
成功了!因为在标准 C++ 中,字符串文字的类型是 const char *
,因此您可以将 const char *convertedValue
分配给 std::string
.