Java 如何将jstring转换为wchar\t* 我们说,在C++方面,我的函数接受了一个变量: jScord命名为 MyScord。我可以将其转换为ANSI字符串,如下所示: const char* ansiString = env->GetStringUTFChars(myString, 0);
有什么方法可以得到它吗Java 如何将jstring转换为wchar\t* 我们说,在C++方面,我的函数接受了一个变量: jScord命名为 MyScord。我可以将其转换为ANSI字符串,如下所示: const char* ansiString = env->GetStringUTFChars(myString, 0);,java,c++,java-native-interface,Java,C++,Java Native Interface,有什么方法可以得到它吗 const wchar\u t*unicodeString=..一个可移植且健壮的解决方案是使用,您必须了解您的系统wchar\u t使用的编码(例如,Windows上的UTF-16,许多Unix系统上的UTF-32) 如果您想最大限度地减少对第三方代码的依赖,您也可以手动滚动您自己的UTF-8转换器。如果转换为UTF-32,这很容易,而使用UTF-16则有点困难,因为您还必须处理代理项对:-P此外,您必须小心拒绝表单,否则在某些情况下可能会打开安全漏洞。如果我们对跨平台
const wchar\u t*unicodeString=
..一个可移植且健壮的解决方案是使用,您必须了解您的系统wchar\u t
使用的编码(例如,Windows上的UTF-16,许多Unix系统上的UTF-32)
如果您想最大限度地减少对第三方代码的依赖,您也可以手动滚动您自己的UTF-8转换器。如果转换为UTF-32,这很容易,而使用UTF-16则有点困难,因为您还必须处理代理项对:-P此外,您必须小心拒绝表单,否则在某些情况下可能会打开安全漏洞。
如果我们对跨平台能力不感兴趣,在windows中,您可以使用MultiByteToWideChar函数,或有用的宏A2W(参考)。
JNI也有一个GetStringChars()函数。返回类型为const jchar*,jchar在win32上为16位,因此在某种程度上与wchar\u t兼容。不确定它是真的UTF-16还是其他什么…
只需使用env->GetStringChars(myString,0);Java pass Unicode就其本质而言我知道这是一年前提出的问题,但我不喜欢其他答案,所以我还是要回答。以下是我们在源代码中的实现方式:
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_______________________________________________?
我推荐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;
}
很简单。但是不要忘记释放StringChars来释放内存
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);
}
如果这对某人有帮助。。。我在一个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;
}
改进的解决方案可以是(感谢反馈):
我试着用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;
}
下面是我如何将
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);
您知道jchar的字节顺序是否与Win32 wchar\u t one兼容吗?应该是这样,但可以肯定的是,这可能很好。:-)jchar类型定义为无符号短字符。我自己没有尝试过,但是我猜是“是”。char=jchar=未签署的16位Schar==哪个平台上的16个符号,让这个稍微不那么混乱,在这个讨论中,“char”是ISO C语言和C++语言中内置的数据类型,而不是在爪哇。你建议把JStUp转换成UTF-8,然后返回UTF-16?这真的有必要吗?@Rup JString已经是UTF-8了:“JNI使用修改的UTF-8字符串来表示各种字符串类型。修改后的UTF-8字符串与JavaVM使用的字符串相同。对修改后的UTF-8字符串进行编码,以便仅包含非空ASCII字符的字符序列可以使用每个字符一个字节来表示,但可以表示所有Unicode字符…..Java VM无法识别标准UTF-8的四字节格式;它使用自己的两倍三字节格式有
typedef unsigned short jchar;
,在我看来更像UTF-16。我一定是误解了什么,那句话是直接从Oracle的文档中引来的:如果可以的话,请随意解释,我仍在努力解决这个问题。除非使用C++11,否则这不是一个很好的解决方案,因为wstring将以值返回。(显然,在C++11之后,它将被移动构造,这将是有效的)value.assign(raw,len);无效。我认为它应该是value.assign(raw,raw+len);但我还没有测试。很好-在C#->C++/CLI->JNI->Java应用程序中对我非常有效!无论GetStringChars成功与否,你都不必调用ReleaseStringChars,否则jstring可能会被钉住,“泄漏”此解决方案是错误的。我为此花了12个小时。wchar\u t和jchar不必是相同的或者那是我的测试程序的输出:01-26 20:28:43.675:E/[LMI-NATIVE](9280):len:7,jchar:2,wchar:4
@Kobor42-你的测试程序是做什么的?你是说你发现了一个wchar\u t是4字节的实例吗?我实际上没有意识到,但这个函数是设计用来运行的(主要是)在wchar______________________________________________________________________________在这种情况下,您需要将UTF-16转换为UTF-32(这不仅仅是将jchar填充为4字节的问题,有关详细信息,请参阅)我不想把它混在一起。NDK想把java字符串转换成信息字符串,但是我怀疑用一个缓冲区加载一个WSCON会更有效地同时一个字符。C++编译器注意到你正在返回一个自动的,并在堆上而不是栈上分配它吗?
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);