Java ™;GetStringChars()未正确翻译字符

Java ™;GetStringChars()未正确翻译字符,java,c++,unicode,java-native-interface,Java,C++,Unicode,Java Native Interface,我注意到商标字符™,该函数应该翻译Unicode字符。我对GetStringUTFChars()方法也有同样的问题 这不是一个大问题,因为有简单的解决方法(在调用JNI函数之前从字符串中删除Unicode字符) 但由于我在谷歌搜索时没有发现类似的问题,我来这里是想看看是否有人对此有解释?(或者我的代码中缺少了什么?) 我在MinGW下使用java8和g++4.8 以下是我的代码片段: JNIEXPORT void JNICALL Java_MyClass_JNI_myMethod (JNIEnv

我注意到商标字符
GetStringChars()
函数似乎没有正确地翻译code>,该函数应该翻译Unicode字符。我对
GetStringUTFChars()
方法也有同样的问题

这不是一个大问题,因为有简单的解决方法(在调用JNI函数之前从字符串中删除Unicode字符)

但由于我在谷歌搜索时没有发现类似的问题,我来这里是想看看是否有人对此有解释?(或者我的代码中缺少了什么?)

我在MinGW下使用java8和g++4.8

以下是我的代码片段:

JNIEXPORT void JNICALL Java_MyClass_JNI_myMethod (JNIEnv * env , jobject obj, jstring input_string)
{
    const jchar *inp_string = (*env).GetStringChars(input_string, NULL);
    const jchar *jch_inp_string = inp_string;         
    (*env).ReleaseStringChars(input_string, inp_string);       

    std::cout << jch_inp_string <<'\n';   
}
它的输出是:

Random Stringâ„¢

在深入研究文档之后,我发现了一个解决方法,这是因为java只支持修改UTF8,这意味着它可以打印XML文档,但不能打印没有错误的拉丁1编码字符

这样做,我从C++调用java,并使他转换了UTF8修改字符,以符合我的需要。 虽然我想知道是否有最简单的方法可以做到这一点,但我发现JNI本机提供的字符串并不完全符合非常常见的标准,这相当奇怪

JNIEXPORT void JNICALL Java_MyClass_JNI_myMethod (JNIEnv * env , jobject obj, jstring input_string){

    //this calls back JNI to reformat the string form java UTF8 modified encoding to something more common
    const jclass stringClass = env->GetObjectClass(input_string);
    const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
    const jstring charsetName = env->NewStringUTF("windows-1252");
    const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(input_string, getBytes, charsetName);
    env->DeleteLocalRef(charsetName);
    const jsize length = env->GetArrayLength(stringJbytes);
    const jbyte* strBytes = env->GetByteArrayElements(stringJbytes, NULL); 


    //this make sure our string is C/C++ compliant with null character
    //but it seems to work well without too
    char* my_string = malloc(length+1);
    memcpy( my_string , strBytes, length);
    my_string [length] = '\0';

    env->ReleaseByteArrayElements(stringJbytes, strBytes , JNI_ABORT); 
    env->DeleteLocalRef(stringJbytes);  

    std::cout << my_string << std::endl;

}
JNIEXPORT void JNICALL Java\u MyClass\u JNI\u myMethod(JNIEnv*env、jobject obj、jstring input\u string){
//这将调用JNI将字符串格式java UTF8 modified encoding重新格式化为更常见的格式
const jclass stringClass=env->GetObjectClass(输入字符串);
const jmethodID getBytes=env->GetMethodID(stringClass,“getBytes”,“(Ljava/lang/String;)[B”);
const jstring charsetName=env->NewStringUTF(“windows-1252”);
const jbyteArray stringJbytes=(jbyteArray)env->CallObjectMethod(input_string,getBytes,charsetName);
env->DeleteLocalRef(charsetName);
const jsize length=env->GetArrayLength(stringJbytes);
常量jbyte*strBytes=env->GetByteArrayElements(stringJbytes,NULL);
//这确保我们的字符串符合C/C++和空字符
//但它似乎在没有太多问题的情况下运行良好
char*my_string=malloc(长度+1);
memcpy(我的字符串,标准字节,长度);
my_字符串[长度]='\0';
env->ReleaseByteArrayElements(字符串字节、标准字节、JNI_中止);
env->DeleteLocalRef(stringJbytes);

如果您使用
std::wcout
而不是
std::cout
,您是否会遇到同样的问题?我的编译器不知道std::wcout,我使用它编译时会出现以下错误:错误:“wout”不是“std”的成员错误:“wout”不是“std”的成员如果你真的写了
wout
而不是
wcout
,那么这个错误是意料之中的。对不起,排版错误,它会给出与上面相同的结果。
jchar
是16位类型,但是
std::cout
需要
char
数据。
GetStringChars()
以UTF-16编码返回Java字符串的字符。由于
jchar
与C++的
char
类型不同,因此将
jchar*
传递给
std::cout
将根本不会打印任何字符,因为它将调用
运算符。此代码完全没有必要。不仅Windows-1252不适用于han删除大多数Unicode字符(您应该使用<代码>”UTF-8“< /Code >,而不是调用<代码> String。GETBySee()/Code >),但此代码也泄漏内存分配,因为您不调用“代码>免费(MyString)(在C++中不应该使用<代码> MalCube())/Code >,使用<代码>新[]
或者更好的
std::string
),如果您觉得需要调用
string.getBytes()
,您不需要分配字节的第二个副本,您可以将原始字节直接传递给
std::cout
,例如:
std::cout.write((char*)strBytes,length);
JNIEXPORT void JNICALL Java_MyClass_JNI_myMethod (JNIEnv * env , jobject obj, jstring input_string){

    //this calls back JNI to reformat the string form java UTF8 modified encoding to something more common
    const jclass stringClass = env->GetObjectClass(input_string);
    const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
    const jstring charsetName = env->NewStringUTF("windows-1252");
    const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(input_string, getBytes, charsetName);
    env->DeleteLocalRef(charsetName);
    const jsize length = env->GetArrayLength(stringJbytes);
    const jbyte* strBytes = env->GetByteArrayElements(stringJbytes, NULL); 


    //this make sure our string is C/C++ compliant with null character
    //but it seems to work well without too
    char* my_string = malloc(length+1);
    memcpy( my_string , strBytes, length);
    my_string [length] = '\0';

    env->ReleaseByteArrayElements(stringJbytes, strBytes , JNI_ABORT); 
    env->DeleteLocalRef(stringJbytes);  

    std::cout << my_string << std::endl;

}