如何在不使用iconv的情况下将C++的std::wstring转换为jstring?
不用iconv把C++的std::wstring转成jstring的方法
没问题!我来给你梳理下不用iconv实现这个转换的方案,其实可以借助JNI自带的方法和C++标准库来搞定,分平台说更清楚:
第一种情况:Windows平台
在Windows上,std::wstring底层的wchar_t是16位的,刚好和JNI里jchar(无符号16位整数)的UTF-16编码匹配,所以直接用JNI的NewString方法就行,完全不需要额外转换:
#include <jni.h> #include <string> jstring wstring_to_jstring(JNIEnv* env, const std::wstring& wstr) { if (wstr.empty()) { return env->NewStringUTF(""); } // Windows下wchar_t和jchar编码兼容,直接强转就行 return env->NewString(reinterpret_cast<const jchar*>(wstr.c_str()), static_cast<jsize>(wstr.size())); }
第二种情况:Linux/macOS平台
类Unix系统里,std::wstring的wchar_t是32位的(对应UTF-32编码),而JNI的jchar是UTF-16格式,这时候需要把UTF-32转成UTF-16。不用iconv的话,C++11及以上的标准库自带的std::wstring_convert和std::codecvt就能搞定:
#include <jni.h> #include <string> #include <locale> #include <codecvt> jstring wstring_to_jstring(JNIEnv* env, const std::wstring& wstr) { if (wstr.empty()) { return env->NewStringUTF(""); } // 把UTF-32的std::wstring转成UTF-16的std::u16string std::wstring_convert<std::codecvt_utf16<char32_t>, char32_t> converter; std::u16string u16str; try { u16str = converter.to_bytes(reinterpret_cast<const char32_t*>(wstr.c_str()), reinterpret_cast<const char32_t*>(wstr.c_str() + wstr.size())); } catch (const std::range_error& e) { // 转换出错的话,给Java层抛个异常提示 env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"), "Invalid UTF-32 string"); return nullptr; } // 用转换后的UTF-16字符串创建jstring return env->NewString(reinterpret_cast<const jchar*>(u16str.c_str()), static_cast<jsize>(u16str.size())); }
跨平台兼容写法
如果你的代码要跑在多个平台上,可以用预编译宏区分不同系统:
#include <jni.h> #include <string> #ifdef _WIN32 jstring wstring_to_jstring(JNIEnv* env, const std::wstring& wstr) { if (wstr.empty()) { return env->NewStringUTF(""); } return env->NewString(reinterpret_cast<const jchar*>(wstr.c_str()), static_cast<jsize>(wstr.size())); } #else #include <locale> #include <codecvt> jstring wstring_to_jstring(JNIEnv* env, const std::wstring& wstr) { if (wstr.empty()) { return env->NewStringUTF(""); } std::wstring_convert<std::codecvt_utf16<char32_t>, char32_t> converter; std::u16string u16str; try { u16str = converter.to_bytes(reinterpret_cast<const char32_t*>(wstr.c_str()), reinterpret_cast<const char32_t*>(wstr.c_str() + wstr.size())); } catch (const std::range_error& e) { env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"), "Failed to convert UTF-32 to UTF-16"); return nullptr; } return env->NewString(reinterpret_cast<const jchar*>(u16str.c_str()), static_cast<jsize>(u16str.size())); } #endif
几个要注意的点
- 得确保你的
std::wstring是对应平台的标准编码(Windows是UTF-16,类Unix是UTF-32),如果是其他编码(比如Windows上的GBK宽字符),那还是得先转成对应平台的标准编码才能用这些方法。 std::wstring_convert在C17里被标记为废弃了,但大部分编译器还是支持的,如果要兼容C17及以后,可以找替代的编码转换实现,不过日常用这个完全够。- 转换过程中记得处理异常,不然容易崩,还可以给Java层抛异常让上层处理问题。
内容的提问来源于stack exchange,提问作者user4122560
相关产品推荐
相关产品推荐

