NewString()& NewStringUTF()显示错误无效修改的UTF-8:

时间:2013-02-19 11:32:25

标签: java android java-native-interface

我正在尝试使用Android中的JNI将char*从C ++传递给java。 我尝试了多种方法来传递数据

1)使用NewStringUTF

const char* data = getData(); // this method returns a char array.
env->NewStringUTF(data);

执行上面的代码会抛出错误

JNI WARNING: input is not valid Modified UTF-8: illegal continuation byte 0x70.

2)使用NewString

const char* data = getData(); // this method returns a char array.
// passing a byte array to java
jbyteArray trackIDArray = env->NewByteArray(strlen(data));
env->SetByteArrayRegion(trackIDArray, 0, strlen(data), (const jbyte*)trackID);

在java方面,我得到一些垃圾值。我不明白如何将这个char数组转换为Java。

4 个答案:

答案 0 :(得分:2)

1)您的data根本不是有效的UTF-8字符串。并非每个char数组都自动为有效的UTF-8。您可能在某些单字节编码(如ISO或Windows CP)中使用它,或者它根本不是可读字符串。

2)应该没问题,但是显示从trackID填充data的代码。您需要将其强制转换为jbyte*的事实是可疑的。 此代码可能是正确的,但您也可能在Java方面犯了错误:

如果data不是可读字符串或者是单字节编码而不是“平台的默认字符集” java.lang.String(byte[]) constructor将无法使用串出来的!在这种情况下,您必须在C端转换为UTF-8。您还将从平台特定编码的依赖性中解脱出来(可能会有很大不同)。

答案 1 :(得分:2)

我怀疑data而不是trackID

env->SetByteArrayRegion(trackIDArray, 0, strlen(data), (const jbyte*)data);

然后你有字节,在java端可能看看它是什么编码 - 通过十六进制转储或其他检查。

随后:

String s = new String(data, "Cp1252"); // Or so.

答案 2 :(得分:2)

NewStringUTF希望您传递Modified UTF-8字符串。 你可能试图通过UTF-8。

有多种方法可以修复它: 最明显的一个是将字符串编码为在C ++中修改的UTF-8,然后再将其传递给Java。

另一种方法是将其作为字节数组传递给Java,并使用String构造函数将其从UTF-16转换。

第二种方式可能更有效,因为最终Java使用UTF-16进行字符串表示。

作为替代方法,您可以在C ++中将字符串转换为UTF-16并将其传递给期望UTF-16的newString JNI函数。

答案 3 :(得分:0)

我在JNI后面放置了很大的字节源(> 2kbyte):

  

csv表的内容:

R"xxx(tbl_Cbla,Column 02,Column 03,Column 04
sdfsdsad,sdfasd,dsfaddf,fdsasdf,fafasa
18,1,10,8,0)xxx"`
std::string data1 =
#include "big_table1.csv" 
;

std::string data2 =
#include "big_table2.csv"
;

extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_example_bigData_rawResource(
        JNIEnv *env,
        jobject /* this */, jint index) {

    std::string values;

    switch (index) {
        case 0: {values = data1;break;}
        case 1: {values = data2;break;}
    }

    int byteCount = values.length();
    jbyteArray ret = env->NewByteArray(byteCount);
    const jbyte* pNativeMessage = reinterpret_cast<const jbyte*>(values.c_str());
    env->SetByteArrayRegion (ret, 0, byteCount, pNativeMessage);
    return ret;
}

在Java中,您可以像这样将其找回,导入本机函数由您决定:

ByteArrayInputStream bis = null;
try {

   bis = new ByteArrayInputStream(rawResource(1);
} catch (Exception e) {
   e.printStackTrace();
}
BufferedReader buffer = new BufferedReader(new InputStreamReader(bis,   Charset.forName("UTF-8")));

例如,要处理缓冲的阅读器,还取决于您:

Strig line = buffer.readLine(); 
while ((line = buffer.readLine()) != null) {
 //play around with 'line'
}