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);