Pergunta

Estou usando o Android NDK para fazer um aplicativo principalmente em C por razões de desempenho, mas parece que operações de arquivo como o FOPEN não funcionam corretamente no Android. Sempre que tento usar essas funções, o aplicativo trava.

Como faço para criar/escrever em um arquivo com o Android NDK?

Foi útil?

Solução

Outras respostas estão corretas. Você pode abrir um arquivo através do ndk usando FILE e fopen, mas não se esqueça de colocar uma permissão para isso.

No Android Manifest Place:

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

Outras dicas

O arquivo IO funciona bem no Android usando o JNI. Talvez você esteja tentando abrir um arquivo com um caminho ruim e não verificar o código de retorno? Modifiquei o exemplo hello-jni para demonstrar que é realmente possível abrir arquivo e gravar nele. Eu espero que isso ajude.

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

Aqui está o resultado depois de executá -lo no meu telefone (com um cartão SD):

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

Certifique -se de usar o java getExternalStorageDirectory() Ligue para obter o caminho real para o SDCARD, já que os dispositivos mais recentes não simplesmente o mapeiam para "/sdcard". Nesse caso, tentar usar um local codificado de "/sdcard" falhará.

Também posso verificar se o fopen () funciona corretamente, mas não Se você está tentando acessar um arquivo na pasta Recursos ou Ativos do aplicativo. Eu recomendo, para evitar reinventar a roda, que você coloque os ativos que deseja enviar com seu aplicativo na pasta de ativos, onde eles serão embalados para distribuição.

No estojo da pasta de ativos, você precisa fazer uma de duas coisas, dependendo se o arquivo foi compactado pelo empacotador. Ambos usam os métodos AssetManager e você pode obter o AssetManager no contexto/aplicativo. Os nomes dos arquivos são sempre relativos à pasta de ativos, btw: se você tiver um arquivo "foo.png" diretamente na pasta ativos, você abriria "foo.png". não algo como "ativos/foo.png".

  1. Se o arquivo não foi compactado (ou seja, é uma das extensões que não é comprimido, como .png), você pode obter um descritor de arquivo de AssetManager.openfd () e passá -lo para C ++. Então você pode usar o FDOPEN (DUP (FD), "R"); Para abrir o arquivo como um arquivo*. Note você Deve fseek () para o deslocamento e acompanhar você mesmo o comprimento do arquivo. Você está realmente recebendo um identificador de arquivo para todo o pacote de ativos, e seu arquivo de interesse é apenas uma pequena parte.

  2. Se o seu arquivo estiver compactado, você precisará usar o leitor de streaming java: AssetManager.open () fornece um InputStream que você pode usar o arquivo de leitura. Este é um pita porque você não pode consultar (AFAIK) o tamanho do arquivo; Eu executo uma etapa de pré -processamento na minha pasta de ativos que gera uma lista de todos os arquivos com seus respectivos tamanhos para que eu possa saber, por exemplo, qual o tamanho de um buffer a alocar.

Se o seu arquivo for um recurso, pode ser necessário passar pela classe de recursos para acessá -lo, embora pareça que os recursos também estejam embalados no mesmo pacote de ativos. O recurso possui uma chamada OpenRawResource () para obter o InputStream e uma chamada OpenRawResourcefd () para obter o descritor de arquivo, como acima.

Boa sorte.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top