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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14956439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 18:00:31  来源:igfitidea点击:

NewString() & NewStringUTF() showing error not valid Modified UTF-8:

javaandroidjava-native-interface

提问by Sagar Ekbote

I am trying to pass char*from C++ to java using JNI in android. I have tried number of ways to pass that data

我正在尝试char*在 android 中使用 JNI 从 C++传递到 java。我已经尝试了多种方法来传递该数据

1) Using NewStringUTF:

1)使用NewStringUTF

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

Executing above code throws below error

执行上面的代码抛出以下错误

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

2) Using NewString:

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

On java side, I am getting some garbage value. I don't understand how to get this chararray to Java.

在 Java 方面,我得到了一些垃圾值。我不明白如何将这个char数组传递给 Java。

回答by Pavel Zdenek

1) your datais simply not a valid UTF-8 string. Not every char array is automatically a valid UTF-8. You probably have it in some single-byte encoding (like ISO or Windows CP), or it's not a readable string at all.

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

2) should be ok, but show the code which fills trackIDfrom data. The fact that you need to hard typecast it to jbyte*is suspicious. This code might be correct, but you can make a mistake on Java side too:

2) 应该没问题,但显示trackIDdata. 您需要对其进行硬类型转换这一事实jbyte*令人怀疑。这段代码可能是正确的,但你也可能在 Java 方面犯错误:

If datais not a readable string or is in single-byte encoding which is not "platform's default charset"java.lang.String(byte[]) constructorwon't be able to make a readable string out of it! In that case, you must convert to UTF-8 on C side. You will also release yourself from the dependency on platform specific encoding (which may be wildly different).

如果data不是可读字符串或不是“平台的默认字符集”的单字节编码,则java.lang.String(byte[]) 构造函数将无法从中生成可读字符串!在这种情况下,您必须在 C 端转换为 UTF-8。您还将摆脱对平台特定编码的依赖(这可能会大不相同)。

回答by Joop Eggen

I would suspect datainstead of trackID.

我会怀疑data而不是trackID.

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

Then you have the bytes and on the java side may look what encoding it is - by a hex dump or other inspection.

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

Later:

之后:

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

回答by Sergey Dryganets

NewStringUTF expects you to pass a Modified UTF-8 string. You are likely trying to pass UTF-8.

NewStringUTF 期望您传递修改后的 UTF-8 字符串。您可能正在尝试通过 UTF-8。

There are multiple ways to fix it: Most obvious one is to encode the string to UTF-8 modified in C++ before passing it to Java.

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

Another way is to pass it to Java as a byte array and use String constructor to convert it from UTF-16.

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

The second way might be more efficient as in the end Java uses UTF-16 for string representation.

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

As an alternative approach, you could convert the string to UTF-16 in C++ and pass it to newString JNI function which expects UTF-16.

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

回答by Nikolai Ehrhardt

I put very big bytesources (>2kbyte) behind the JNI like this :

我将非常大的字节源(> 2kbyte)放在 JNI 后面,如下所示:

Content of a csv-table:

R"xxx(tbl_Cbla,Column 02,Column 03,Column 04
sdfsdsad,sdfasd,dsfaddf,fdsasdf,fafasa
18,1,10,8,0)xxx"`

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

In Java you can get it back like this, to import the native function is up to you:

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

To to handle the buffered reader is also up to you, small exg.:

处理缓冲阅读器也取决于你,小例子:

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