Question

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

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

Était-ce utile?

La solution

D'autres réponses sont correctes

. Vous pouvez ouvrir un fichier à travers le NDK en utilisant FILE et fopen, mais ne pas oublier de placer une autorisation pour cela.

Dans le lieu manifeste Android:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

Autres conseils

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

/*
 * 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'exécution sur mon téléphone (avec une carte SD):

$ adb -d shell cat /sdcard/hello.txt
HELLO WORLD!

Assurez-vous d'utiliser l'appel Java getExternalStorageDirectory() pour obtenir le chemin réel au sdcard puisque les appareils les plus récents ne correspondent pas simplement à « / sdcard ». Dans ce cas, essayez d'utiliser un emplacement de hardcoded « / sdcard » échouera.

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

Dans le cas des actifs dossier que vous devez faire l'une des deux choses, selon que le fichier a été compressé par l'emballeur. Les deux utilisent les méthodes de AssetManager, et vous pouvez obtenir le AssetManager du contexte / app. Les noms de fichiers sont toujours par rapport au dossier actif, BTW: Si votre disposez d'un fichier « foo.png » directement dans le dossier actif, vous souhaitez ouvrir « foo.png, » pas quelque chose comme « actifs /foo.png ».

  1. Si le fichier n'a pas été compressé (elle est l'une des extensions qui ne soit pas comprimé, comme .png), vous pouvez obtenir un descripteur de fichier de AssetManager.openFd () et le transmettre à C ++ . Ensuite, vous pouvez utiliser fdopen (dup (fd), "r"); pour ouvrir le fichier en tant que FILE *. Notez que vous doit fseek () à l'offset, et de garder une trace de la longueur du fichier vous-même. Vous êtes vraiment obtenir un handle de fichier sur l'ensemble du paquet d'actifs, et votre dossier d'intérêt est seulement petite partie.

  2. Si votre fichier est compressé, vous devez utiliser le lecteur de streaming Java: AssetManager.open () vous donne un InputStream vous pouvez utiliser le lire le fichier dans c'est un PITA parce que vous ne pouvez pas interroger (. AFAIK) la taille du fichier; Je dirige une étape de pré-traitement sur mon dossier actif 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 de ressources pour y accéder, mais il semble des ressources sont également emballés dans le même paquet d'actifs. Ressources a un openRawResource () pour obtenir le InputStream et un openRawResourceFd () pour obtenir le descripteur de fichier, comme ci-dessus, cependant.

Bonne chance.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top