Operaciones de archivos en Android NDK


Estoy usando el NDK de Android para hacer una aplicación principalmente en C por razones de rendimiento, pero parece que las operaciones de archivos como fopen no funcionan correctamente en Android. Cada vez que intento usar estas funciones, la aplicación se bloquea.

¿Cómo puedo crear/escribir en un archivo con el NDK de Android?

Author: Janusz, 2010-01-03

4 answers

Todo lo anterior es correcto. Puede abrir un archivo a través del NDK usando FILE y fopen. PERO... No se olvide de colocar un permiso para ello. en el manifiesto de Android coloque un

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
 54
Author: Ita,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-16 14:32:20

File IO funciona bien en Android usando JNI. Tal vez usted está tratando de abrir un archivo con una mala ruta y no comprobar el código de retorno? Modifiqué el ejemplo de hello-jni para demostrar que de hecho es posible abrir el archivo y escribir en él. Espero que esto ayude.

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <string.h>
#include <jni.h>
#include <stdio.h>

/* This is a trivial JNI example where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
 */
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                              jobject thiz )
{
    FILE* file = fopen("/sdcard/hello.txt","w+");

    if (file != NULL)
    {
        fputs("HELLO WORLD!\n", file);
        fflush(file);
        fclose(file);
    }

    return (*env)->NewStringUTF(env, "Hello from JNI (with file io)!");
}

Aquí está el resultado después de ejecutarlo en mi teléfono (con una tarjeta SD):

$ adb -d shell cat /sdcard/hello.txt
HELLO WORLD!
 57
Author: Tim Kryger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-03 00:19:08

También puedo verificar que fopen() funciona correctamente, pero no si estás intentando acceder a un archivo en la carpeta resources o assets de la aplicación. Recomiendo, para evitar tener que reinventar la rueda, que pegue cualquier activo que desee enviar con su aplicación en la carpeta de activos, donde se empaquetarán para su distribución.

En el caso de la carpeta assets necesita hacer una de dos cosas, dependiendo de si el archivo fue comprimido por el empaquetador. Ambos usan AssetManager métodos, y puede obtener el AssetManager desde el contexto / aplicación. Los nombres de archivo son siempre relativos a la carpeta assets, por cierto: Si tiene un archivo " foo.png "directamente en la carpeta assets, abrirías" foo.png, "no algo así como " assets/foo.png".

  1. Si el archivo no estaba comprimido (es decir, es una de las extensiones que no se comprime, como .png), puede obtener un descriptor de archivo de AssetManager.openFd () y pasarlo a C++. Luego puedes usar fdopen(dup (fd),"r"); para abra el archivo como un ARCHIVO*. Tenga en cuenta que debe fseek() al desplazamiento, y mantener un registro de la longitud del archivo usted mismo. Realmente está obteniendo un controlador de archivo para todo el paquete assets, y su archivo de interés es solo una pequeña parte.

  2. Si su archivo está comprimido, debe usar Java streaming reader: AssetManager.open() le da un flujo de entrada que puede usar para leer el archivo. Esto es un PITA porque no puede consultar (AFAIK) el tamaño del archivo; corro un paso de preprocesamiento en mi carpeta de activos que genera una lista de todos los archivos con sus respectivos tamaños para que pueda saber, por ejemplo, el tamaño de un búfer para asignar.

Si su archivo es un recurso, es posible que necesite pasar por la clase Resource para acceder a él, aunque parece que los recursos también están empaquetados en el mismo paquete assets. Resource tiene una llamada a openRawResource () para obtener el InputStream y una llamada a openRawResourceFd () para obtener el descriptor de archivo, como se ha mencionado anteriormente.

Buena suerte.

 19
Author: SomeCallMeTim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-24 16:30:56

Asegúrese de usar la llamada Java getExternalStorageDirectory() para obtener la ruta real a la tarjeta SD, ya que los dispositivos más nuevos no simplemente la asignan a "/sdcard". En ese caso, intentar usar una ubicación hardcoded de "/ sdcard " fallará.

 19
Author: niko20,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-04 12:49:42