Конвертировать jcharArray в String с правильной кодировкой jni

0

У меня есть собственный метод, который возвращает массив файлов в каталоге. public static native char [] [] scan (String path); Я не могу вернуть массив строк, потому что, если файл имеет недопустимый encoding-, все сбои. Проблема заключается в правильном преобразовании char [] в String на стороне java, когда я пытаюсь использовать новую строку String (chars); Я получаю непечатаемую строку (недействительно). Пожалуйста, поправьте меня.

Вот пример вывода (если метод возвращает String [])

Array.toString(scan("/storage/")); → [/storage/sdcard1,/storage/sdcard0]

Вот если метод возвращает 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����]

Что происходит на стороне C: если метод возвращает 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;
}

Что происходит на стороне C: если метод возвращает 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;
    }
Теги:
android-ndk
jni

1 ответ

2

Вы не можете использовать NewStringUTF для строк, отличных от MUTF8 (где MUTF8 - это "модифицированный UTF-8", определенный спецификацией JNI).

Вам нужно либо преобразовать локальный набор символов в UTF-16 в собственный код, а затем использовать NewString или передать массивы byte[] в ваш код Java, а затем использовать конструктор String, который принимает аргумент charset. Используемая кодировка зависит от того, что поддерживает ваша файловая система.

Прямо сейчас вы либо помещаете данные без MUTF8 в NewStringUTF, которые будут шумно звучать, если CheckJNI включен, или вы помещаете байтовые значения в символы UTF-16 без преобразования кодировки.

  • 0
    Я пробовал также byte [] (вместо char []), с разными наборами символов (utf-8, utf-16, us-ansii), в результате получается нечитаемые имена файлов. Это проблема.
  • 0
    Вам нужно найти кодировку, соответствующую вашей файловой системе. Вы знаете, какую кодировку он использует? Если вы не уверены, добавьте шестнадцатеричный дамп некоторых проблемных имен файлов (вместе с ожидаемым внешним видом) к вопросу, и, возможно, кто-то его узнает. Начните с чего-то простого, например, с имени, состоящего из символов ASCII, с чем-то необычным в середине. (И если имена файлов все ASCII, то еще что - то происходит.)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню