web-dev-qa-db-fra.com

Opérations sur les fichiers dans Android NDK

J'utilise le Android NDK pour créer une application principalement en C pour des raisons de performances, mais il semble que les opérations sur les fichiers telles que fopen ne fonctionnent pas correctement dans Android. Chaque fois que j'essaie d'utiliser ces fonctions, l'application se bloque.

Comment créer/écrire dans un fichier avec le NDK Android?

62
RyanCheu

D'autres réponses sont correctes. Vous pouvez ouvrir un fichier via le NDK en utilisant FILE et fopen, mais n'oubliez pas de lui accorder une autorisation.

À l'emplacement Android manifeste:

<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/> 
59
Ita

Fichier IO fonctionne bien sur Android en utilisant JNI. Peut-être que vous essayez d'ouvrir un fichier avec un mauvais chemin et que vous ne vérifiez pas le code de retour? J'ai modifié le bonjour -jni exemple pour démontrer qu'il est effectivement possible d'ouvrir un fichier et d'y écrire. J'espère que cela vous aidera.

/*
 * 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)!");
}

Voici le résultat après l'avoir exécuté sur mon téléphone (avec une carte SD):

$ adb -d Shell cat /sdcard/hello.txt
HELLO WORLD!
61
Tim Kryger

Assurez-vous d'utiliser l'appel Java getExternalStorageDirectory() pour obtenir le chemin réel vers la carte SD car les nouveaux appareils ne la mappent pas simplement à "/ sdcard". Dans ce cas, essayez pour utiliser un emplacement codé en dur de "/ sdcard" échouera.

23
niko20

Je peux également vérifier que fopen () fonctionne correctement, mais pas si vous essayez d'accéder à un fichier dans le dossier de ressources ou d'actifs de l'application. Je recommande, pour éviter d'avoir à réinventer la roue, de coller tous les actifs que vous souhaitez expédier avec votre application dans le dossier des actifs, où ils seront emballés pour la distribution.

Dans le cas du dossier d'actifs, vous devez effectuer l'une des deux opérations suivantes, selon que le fichier a été compressé ou non par le packager. Les deux utilisent les méthodes AssetManager et vous pouvez obtenir AssetManager à partir du contexte/de l'application. Les noms de fichiers sont toujours relatifs au dossier des ressources, btw: si vous avez un fichier "foo.png" directement dans le dossier des ressources, vous ouvririez "foo.png", pas quelque chose comme "ressources /foo.png ".

  1. Si le fichier n'a pas été compressé (c'est-à-dire qu'il s'agit de l'une des extensions qui ne sont pas compressées, comme .png), vous pouvez obtenir un descripteur de fichier depuis AssetManager.openFd () et le transmettre à C++. Ensuite, vous pouvez utiliser fdopen (dup (fd), "r"); pour ouvrir le fichier en tant que FICHIER *. Notez que vous devez fseek () pour le décalage, et gardez une trace de la longueur du fichier vous-même. Vous obtenez vraiment un descripteur de fichier pour l'ensemble des actifs, et votre fichier d'intérêt n'est qu'un petite partie.

  2. Si votre fichier est compressé, vous devez utiliser le Java: AssetManager.open () vous donne un InputStream dans lequel vous pouvez utiliser la lecture du fichier. Il s'agit d'un PITA car vous pouvez ' t interroger (AFAIK) la taille du fichier; j'exécute une étape de prétraitement sur mon dossier d'actifs qui génère une liste de tous les fichiers avec leurs tailles respectives afin que je puisse savoir, par exemple, la taille d'un tampon à allouer.

Si votre fichier est une ressource, vous devrez peut-être passer par la classe Resource pour y accéder, bien qu'il semble que les ressources soient également regroupées dans le même package d'actifs. La ressource a un appel openRawResource () pour obtenir InputStream et un appel openRawResourceFd () pour obtenir le descripteur de fichier, comme ci-dessus, cependant.

Bonne chance.

21
SomeCallMeTim