#android #c #json #boost #cmake
Вопрос:
Как правильно открыть файл с помощью boost::property_tree::json_parser::read_json
Текущее дерево:
boost::property_tree::ptree config;
boost::property_tree::json_parser::read_json("conf/file.json", config);
Но я получаю сообщение об ошибке, что он не может найти файл
завершается с неперехваченным исключением типа boost::wrapexceptboost::property_tree::json_parser::json_parser_error: conf/файл.json: не удается открыть файл
Как бы я продолжил копирование файла на устройство и смог бы его открыть?
Комментарии:
1. проверьте текущий каталог и, соответствует ли он ожидаемому пути. Убедитесь, что файл конфигурации был загружен в ожидаемое место.
2. Поместите файлы в
assets
папку и используйте библиотеку ресурсов JNI для доступа к ним.3. @MarekR Как мне убедиться и проверить, был ли он загружен в нужное место?
4. @RichardCritten это работает с boost?
5. @RichardCritten как мне конвертировать
InputStream
в boostptree
, была бы признательна любая помощь?
Ответ №1:
Я использовал этот код, чтобы заставить его работать, в основном вы копируете файл из Android raw
dir в какое-то место на устройстве, которое может видеть код C JNI.
MainActivity
код:
private static final String RES_RAW_CONFIG_PATH_ENV_VAR = "RES_RAW_CONFIG_PATH";
private static final String RES_RAW_CONFIG_FILE_NAME = "res_raw_config.json";
@Override
protected void onCreate(Bundle savedInstanceState) {
initResRawConfig(true); // this will copy the file
...
}
private boolean existsInFilesDir(String fileName) {
val file = File(filesDir, fileName)
return file.exists()
}
private void initResRawConfig(boolean forceCopy) {
if (existsInFilesDir(RES_RAW_CONFIG_FILE_NAME) amp;amp; !forceCopy) {
Log.d(TAG, "Config file: " RES_RAW_CONFIG_FILE_NAME " already exists in " getFilesDir().toString());
}
else {
copyFileFromResToFilesDir(R.raw.res_raw_config, RES_RAW_CONFIG_FILE_NAME);
Log.d(TAG, "Config file: " RES_RAW_CONFIG_FILE_NAME " copied to " getFilesDir().toString());
}
// Set Environment Variable to get path from native
try {
Os.setenv(RES_RAW_CONFIG_PATH_ENV_VAR, getFilesDir().getAbsolutePath(), true);
} catch (ErrnoException e) {
e.printStackTrace();
}
}
private void copyFileFromResToFilesDir(int fromResId, String toFile) {
InputStream is = getResources().openRawResource(fromResId);
byte[] buffer = new byte[4096];
try
{
FileOutputStream fos = openFileOutput(toFile, Context.MODE_PRIVATE);
int bytes_read;
while ((bytes_read = is.read(buffer)) != -1)
fos.write(buffer, 0, bytes_read);
fos.close();
is.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public String getResRawConfigDir()
{
return getFilesDir().toString();
}
JNI
код:
// get file path from java method
std::string getResRawConfigDirFromJava(JNIEnv *env, jobject obj) {
jclass clazz = env->GetObjectClass(obj); // or env->FindClass("com/example/myapp/MainActivity");
jmethodID method = env->GetMethodID(clazz, "getResRawConfigDir", "()Ljava/lang/String;");
jobject ret = env->CallObjectMethod(obj, method);
auto jConfigDirPath = (jstring) ret;
return std::string(env->GetStringUTFChars(jConfigDirPath, nullptr));
}
extern "C" JNIEXPORT jstring
sampleFunc(JNIEnv *env, jobject thiz) {
std::string configPath = getResRawConfigDirFromJava(env, thiz);
std::string filePath = configPath "/" "res_raw_config.json";
}