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
NewString() & NewStringUTF() showing error not valid Modified UTF-8:
提问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 char
array to Java.
在 Java 方面,我得到了一些垃圾值。我不明白如何将这个char
数组传递给 Java。
回答by Pavel Zdenek
1) your data
is 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 trackID
from 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) 应该没问题,但显示trackID
从data
. 您需要对其进行硬类型转换这一事实jbyte*
令人怀疑。这段代码可能是正确的,但你也可能在 Java 方面犯错误:
If data
is 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 data
instead 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'
}