2017-04-02 57 views
2

我注意到商标字符似乎没有被Java 8中的JNI的GetStringChars()函数正确地转换,它被认为是翻译Unicode字符的函数。我有与GetStringUTFChars()方法相同的问题。™字符没有被GetStringChars()正确翻译

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

但是,由于我没有发现类似的问题,而谷歌搜索,我来这里看看有没有人有关于此的解释? (或者我可能在我的代码中缺少某些东西?)

我在MinGW下使用Java 8和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™ 

它输出该:

Random Stringâ„¢ 
+0

如果使用'std :: wcout'而不是'std :: cout',你有同样的问题吗? – Michael

+0

std :: wcout对我的编译器来说是未知的,当我编译它时出现这个错误:error:'wout'不是'std'的成员 –

+0

_“错误:'wout'不是'std' “_如果你真的写了'wout'而不是'wcout',那么这个错误是可以预料的。 – Michael

回答

0

我在docs深入了解之后发现了一个解决方法,这是因为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; 

} 
+0

这段代码是完全不必要的。不仅Windows-1252不适合处理大多数Unicode字符(您应该在调用'String.getBytes()'时使用'“utf-8”'),但是这个代码也会泄漏分配的内存不会调用'free(my_string)'(你甚至不应该在C++中使用'malloc()',而应该使用'new []'或者更好的'std :: string')。如果你觉得需要调用'String.getBytes()',你不需要分配第二个字节的副本,你可以直接将原始字节传递给'std :: cout',例如:'std :: cout.write((char *)strBytes,length);' –