sistemas - Operaciones de archivos en Android NDK
operaciones con archivos sistemas operativos (4)
Asegúrese de utilizar la getExternalStorageDirectory()
Java getExternalStorageDirectory()
para obtener la ruta real a la tarjeta sd, ya que los dispositivos más nuevos no la asignan a "/ sdcard". En ese caso, intentar usar una ubicación codificada de "/ sdcard" fallará.
Estoy usando Android NDK 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 falla.
¿Cómo creo / escribo en un archivo con el NDK de Android?
File IO funciona bien en Android usando JNI. ¿Quizás estás tratando de abrir un archivo con una ruta incorrecta y no verificar 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!
También puedo verificar que fopen () funciona correctamente, pero no si está intentando acceder a un archivo en la carpeta de recursos o activos de la aplicación. Recomiendo, para evitar tener que reinventar la rueda, que coloque los activos que desea enviar con su aplicación en la carpeta de activos, donde se empaquetarán para su distribución.
En el caso de carpeta de activos, debe hacer una de estas dos cosas, dependiendo de si el paquete fue comprimido. Ambos usan los métodos de AssetManager, y usted puede obtener AssetManager del contexto / aplicación. Los nombres de archivo siempre son relativos a la carpeta de activos, por cierto: si tiene un archivo "foo.png" directamente en la carpeta de activos, abriría "foo.png", no algo así como "assets / foo.png".
Si el archivo no se comprimió (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 ++. Entonces puedes usar fdopen (dup (fd), "r"); para abrir el archivo como un ARCHIVO *. Tenga en cuenta que debe fseek () para el desplazamiento y realizar un seguimiento de la longitud del archivo usted mismo. Realmente está obteniendo un identificador de archivo para todo el paquete de activos, y su archivo de interés es solo una pequeña parte.
Si su archivo está comprimido, necesita usar el lector de flujo de Java: AssetManager.open () le proporciona un InputStream en el que puede leer el archivo. Esto es un PITA porque no puede consultar (AFAIK) el tamaño del archivo; Ejecuto un paso de preproceso en mi carpeta de activos que genera una lista de todos los archivos con sus respectivos tamaños para que pueda saber, por ejemplo, qué tan grande de un búfer para asignar.
Si su archivo es un recurso, puede necesitar ir a la clase de Recursos para acceder a él, aunque parece que los recursos también están empaquetados en el mismo paquete de activos. El recurso tiene una llamada a openRawResource () para obtener el InputStream y una llamada a openRawResourceFd () para obtener el descriptor del archivo, como el anterior.
Buena suerte.
Todo lo anterior es correcto. Puede abrir un archivo a través del NDK usando FILE y fopen. PERO ... No olvides dar un permiso para ello. en el manifiesto Android colocar un
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>