簡體   English   中英

無法在JNI中編碼為UTF-8

[英]Cannot encode to UTF-8 in JNI

我試圖返回用UTF-8編碼的jstring,但是應用程序崩潰並且JNI寫出錯誤:

JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal continuation byte 0x30

我的片段:

jstring Java_tgio_rncryptor_RNCryptorNative_generateKey(JNIEnv *env, jobject instance, const jstring salt_, const jstring password_)
 {
    const char *salt = env->GetStringUTFChars(salt_, 0);
    const char *password = env->GetStringUTFChars(password_, 0);
    RNCryptor *cryptor = new RNCryptor();
    string value = (char * )cryptor->generateKey(salt, password).data();
    delete cryptor;
    env->ReleaseStringUTFChars(salt_, salt);
    env->ReleaseStringUTFChars(password_, password);
    return env->NewStringUTF(value.c_str());
}

還嘗試了:

const char *returning = env->GetStringUTFChars(env->NewStringUTF(value.c_str()), 0);
return env->NewStringUTF(returning);

有什么建議么?

cryptor->generateKey返回SecByteBlock ,一個字節序列。 當強制轉換為(char *)並構造std::string因為它們不僅僅處理文本,所以jstring保留文本(來自UTF-16編碼的Unicode字符集)。

您的代碼嘗試將非文本字節轉換為Java字符串。 如果確實要這樣做,則必須使用字符集和編碼,其任何值序列0-255均有效。 (CP437就是其中之一。)

但是,相反,您可以將數據保留在更接近數據類型的數據類型中:返回Java byte[] 然后在Java端,如果要將密鑰作為字符串傳遞,則可以將字節序列轉換為Base 64

通常,密碼算法對字節序列或塊進行操作。 處理文本的只是應用程序或包裝函數。 您將檢查RNCryptor是否為您執行此操作,但是對我而言,它看起來不是那樣。

嘗試將此代碼用於UTF-8

  try {
URLEncoder.encode(yourValue, "UTF-8")

} catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

並非所有字節都是有效的可打印字符,並且大多數不是有效的unicode字符。 當需要將字節數組編碼為字符串時,標准做法是使用Base64或十六進制。

我通過返回jcharArray而不是jstring解決了問題:

     env->ReleaseStringUTFChars(salt_, salt);
     env->ReleaseStringUTFChars(password_, password);
     char array[1024];
     strcpy(array, value.c_str());
     jcharArray charArr = env->NewCharArray(1024);
     env->SetCharArrayRegion(charArr, 0, 1024, (jchar *) array);
     return charArr;

我只是在Java源代碼中執行了String.valueOf(arr)並將其打印出來。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM