Dateioperationen in Android NDK

Lesezeit: 5 Minuten

Benutzeravatar von RyanCheu
Ryan Cheu

Ich verwende das Android NDK, um eine Anwendung aus Leistungsgründen hauptsächlich in C zu erstellen, aber es scheint, dass Dateioperationen wie fopen in Android nicht richtig funktionieren. Immer wenn ich versuche, diese Funktionen zu verwenden, stürzt die Anwendung ab.

Wie erstelle/schreibe ich eine Datei mit dem Android NDK?

  • Entschuldigung, vergessen, dies zu aktualisieren. Die Wurzel des Problems bestand darin, keine Lese-/Schreibberechtigungen zu erhalten. Ein ähnliches Problem kann auch dadurch verursacht werden, dass die SD-Karte gemountet ist und dann versucht wird, eine darin enthaltene Datei zu öffnen.

    – RyanCheu

    24. Oktober 2011 um 19:31 Uhr

Benutzeravatar von Ita
Ita

Andere Antworten sind richtig. Sie können eine Datei über das NDK mit öffnen FILE und fopenaber vergessen Sie nicht, eine Berechtigung dafür zu platzieren.

Im Android-Manifest:

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

  • Im Manifest developer.android.com/guide/topics/manifest/…

    – James Alvarez

    20. Februar 2015 um 17:57 Uhr

  • Danke, es funktioniert! Und ich habe auch herausgefunden, dass die Updates in der Manifestdatei erst wirksam werden, nachdem Sie die App neu installiert haben. Manchmal installiert die Sonnenfinsternis die App nicht neu für Sie. Ich lösche die App auf meinem Telefon und installiere sie mit Eclipse neu.

    – Iching Chang

    16. Juni 2015 um 2:17 Uhr

Benutzeravatar von Tim Kryger
Tim Kryger

File IO funktioniert gut auf Android mit JNI. Vielleicht versuchen Sie, eine Datei mit einem ungültigen Pfad zu öffnen und überprüfen den Rückgabecode nicht? Ich habe das hello-jni-Beispiel modifiziert, um zu demonstrieren, dass es tatsächlich möglich ist, eine Datei zu öffnen und in sie zu schreiben. Ich hoffe das hilft.

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

Hier ist das Ergebnis, nachdem ich es auf meinem Telefon (mit einer SD-Karte) ausgeführt habe:

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

  • Danke, das funktioniert! Ich denke, mein Problem war, dass ich keinen vollständigen Pfad für meinen fopen-Befehl verwendet habe.

    – RyanCheu

    3. Januar 2010 um 2:19 Uhr

  • Wäre es möglich, eine Datei, die sich in Assets befindet, im schreibgeschützten Modus zu öffnen?

    – DR

    31. Mai 2010 um 10:35 Uhr

  • Das Öffnen von Assets mit dem NDK ist komplizierter, aber ich beschreibe hier die erforderlichen Schritte.

    – Tim Kryger

    31. Mai 2010 um 17:23 Uhr

Benutzeravatar von niko20
Niko20

Stellen Sie sicher, dass Sie Java verwenden getExternalStorageDirectory() aufrufen, um den tatsächlichen Pfad zur SD-Karte zu erhalten, da neuere Geräte ihn nicht einfach auf „/sdcard“ abbilden. In diesem Fall schlägt der Versuch, einen fest codierten Speicherort von „/sdcard“ zu verwenden, fehl.

  • Das ist in der Tat sehr wichtig

    – KaiserJohaan

    1. März 2012 um 19:26 Uhr

  • Lauf adb shell "ls / -l | grep sdcard" um herauszufinden, wo Ihr Gerät auch das /sdcard-Verzeichnis abbildet (für Debugging-Zwecke)

    – FrickeFresh

    3. Februar 2019 um 2:36 Uhr

  • Anstatt zu verwenden getExternalStorageDirectory Ich habe getenv (“EXTERNAL_STORAGE”) verwendet, aber es hat nicht funktioniert. Obwohl auf Adb-Shell $EXTERNAL_STORAGE ist /sdcard/. Ich verwende Android 7.1. Soll ich den Pfad mit bekommen getExternalStorageDirectory?

    – kanna

    18. April 2019 um 20:25 Uhr

Ich kann auch überprüfen, ob fopen() korrekt funktioniert, aber nicht wenn Sie versuchen, auf eine Datei im Ordner „Ressourcen“ oder „Assets“ der Anwendung zuzugreifen. Damit Sie das Rad nicht neu erfinden müssen, empfehle ich Ihnen, alle Assets, die Sie mit Ihrer App versenden möchten, in den Assets-Ordner zu stecken, wo sie für die Verteilung gepackt werden.

Im Fall des Assets-Ordners müssen Sie eines von zwei Dingen tun, je nachdem, ob die Datei vom Packager komprimiert wurde. Beide verwenden die AssetManager-Methoden, und Sie können den AssetManager aus dem Kontext/der App abrufen. Dateinamen sind immer relativ zum Assets-Ordner, übrigens: Wenn Sie eine Datei „foo.png“ direkt im Assets-Ordner haben, würden Sie „foo.png“ öffnen. nicht so etwas wie “assets/foo.png”.

  1. Wenn die Datei nicht komprimiert wurde (dh es handelt sich um eine der Erweiterungen, die nicht komprimiert wird, wie .png), können Sie einen Dateideskriptor von AssetManager.openFd() abrufen und an C++ übergeben. Dann können Sie fdopen(dup(fd),”r”); um die Datei als DATEI* zu öffnen. Beachten Sie müssen fseek() auf den Offset setzen und die Länge der Datei selbst verfolgen. Sie erhalten wirklich eine Dateikennung für das gesamte Asset-Paket, und Ihre Datei von Interesse ist nur ein kleiner Teil.

  2. Wenn Ihre Datei komprimiert ist, müssen Sie den Java-Streaming-Reader verwenden: AssetManager.open() gibt Ihnen einen InputStream, mit dem Sie die Datei einlesen können. Dies ist ein PITA, da Sie die Dateigröße nicht abfragen können (AFAIK); Ich führe einen Vorverarbeitungsschritt für meinen Assets-Ordner aus, der eine Liste aller Dateien mit ihren jeweiligen Größen generiert, damit ich zB wissen kann, wie groß der zuzuweisende Puffer ist.

Wenn Ihre Datei eine Ressource ist, müssen Sie möglicherweise die Ressourcenklasse durchlaufen, um darauf zuzugreifen, obwohl es scheint, dass Ressourcen auch in dasselbe Asset-Paket gepackt sind. Resource hat einen openRawResource()-Aufruf, um den InputStream zu erhalten, und einen openRawResourceFd()-Aufruf, um den Dateideskriptor wie oben zu erhalten.

Viel Glück.

Ich möchte meine zwei Cent zu den Antworten hier hinzufügen. Stellen Sie zusätzlich zum Festlegen der korrekten Berechtigungen, die in der Antwort auf diese Frage angegeben sind, sicher, dass Sie Ihrer App die Berechtigung zum Zugriff auf den Speicher im Betriebssystem erteilen. Das Berechtigungsmenü kann sich von Telefon zu Telefon ändern. Eine einfache Möglichkeit, dorthin zu gelangen, besteht darin, zum Menü „Einstellungen“ zu gehen und dann nach „Berechtigungen“ zu suchen. Dies gibt Ihnen die Möglichkeit, Ihrer App die Erlaubnis zu erteilen, über den NDK-Code auf den Speicher (dh das SD-Kartenverzeichnis) zuzugreifen.

1416960cookie-checkDateioperationen in Android NDK

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy