Reputation: 1029
I have native method that return array of files in directory. public static native char[][] scan(String path); I can't return array of strings because if file has invalid encoding- everything crashes The problem is correctly convert char[] to String on java side, when i try new String(chars); i get unprintable string (invalid). Please correct me.
Here is example of output (If method return String[])
Array.toString(scan("/storage/"));
-> [/storage/sdcard1, /storage/sdcard0]
Here is if method return char[][];
char[][] chars = scan("/storage/");
String[] stringArray = new String[char.length];
for(int i = 0; i < chars.length; i++){
stringArray[i] = new String(char[i]);
}
Arrays.toString(stringArray); -> //unprintable symbols [����������爀条⽥摳慣摲쉮R����,����������爀条⽥摳慣摲쉮R����]
What happens on C side: if method return String[]
jobjectArray scan(JNIEnv *env, jclass cls,jstring jpath){
std::vector<std::string> data;//contains some strings
unsigned int size = data.size();
jobjectArray ret = env->NewObjectArray(size,env->FindClass("java/lang/String"),NULL);
for (unsigned int i = 0; i < size; i++){
env->SetObjectArrayElement(ret,i,env->NewStringUTF(data.at(i).c_str()));
}
return ret;
}
What happens on C side: if method return char[][];
jobjectArray scan(JNIEnv *env, jclass cls,jstring jpath){
std::vector<std::string> data;//contains some strings
unsigned int size = data.size();
jobjectArray ret = env->NewObjectArray(size, env->FindClass("[C"), NULL);
for (unsigned int i = 0; i < size; i++){
env->SetObjectArrayElement(ret,i,env->NewStringUTF(toChar(env,data.at(i))));
}
return ret;
}
jcharArray toChar(JNIEnv *env, string string) {
unsigned int n=0;
const char* p = string.c_str();
while(*p++){
n++;
} if(n<=0)
return NULL;
jcharArray arr = env->NewCharArray(n);
env->SetCharArrayRegion(arr,0,n, (jchar*)p);
return arr;
}
Upvotes: 0
Views: 1280
Reputation: 52313
You can't use NewStringUTF
on non-MUTF8 strings (where MUTF8 is the "modified UTF-8" defined by the JNI spec).
You either need to convert the local character set to UTF-16 in native code and then use NewString
, or pass arrays of byte[]
into your Java code and then use the String constructor that takes a charset argument. The Charset to use depends on what your filesystem supports.
Right now you're either putting non-MUTF8 data into NewStringUTF
, which will fail noisily if CheckJNI is enabled, or you're putting byte values into UTF-16 chars without doing a charset conversion.
Upvotes: 2