Android NDK中的文件操作

由于性能的原因,我正在使用Android NDK来创build一个主要用于C的应用程序,但似乎fopen等文件操作在Android中无法正常工作。 每当我尝试使用这些函数,应用程序崩溃。

如何使用Android NDK创build/写入文件?

以上所有都是正确的。 您可以使用FILE和fopen通过NDK打开一个文件。 但是…不要忘记放置一个许可。 在Android manifest中放置一个

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

文件IO使用JNI在Android上正常工作。 也许你正试图打开一个坏path的文件,而不是检查返回码? 我修改了hello-jni示例来演示如何打开文件并写入文件。 我希望这有帮助。

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

以下是在我的手机上运行(使用SD卡)后的结果:

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

请确保使用Java getExternalStorageDirectory()调用来获取sdcard的真实path,因为新设备不会简单地将其映射到“/ sdcard”。 在这种情况下,试图使用“/ sdcard”的硬编码位置将会失败。

我也可以validationfopen()是否正常工作,但是如果你正在尝试访问应用程序资源或资产文件夹中的文件,则不能。 为避免重蹈覆辙,我build议您将随应用程序一起提供的所有资产都粘贴到资产文件夹中,然后将其打包分发。

在资产文件夹的情况下,您需要执行以下两项操作之一,具体取决于文件是否被打包程序压缩。 两者都使用AssetManager方法,您可以从上下文/应用程序获取AssetManager。 文件名总是相对于assets文件夹,btw:如果你在assets文件夹中直接有一个文件“foo.png”,你会打开“foo.png”, 而不是像“assets / foo.png”。

  1. 如果文件没有被压缩(即它是一个没有被压缩的扩展名,比如.png),你可以从AssetManager.openFd()获得一个文件描述符并传递给C ++。 那么你可以使用fdopen(dup(fd),“r”); 以FILE *的forms打开文件。 请注意,您必须将fseek()设置为偏移量,并自行跟踪文件的长度。 你真的得到了整个资产包的文件句柄,而你感兴趣的文件只是一小部分。

  2. 如果您的文件是压缩的,您需要使用Javastream式阅读器:AssetManager.open()为您提供了一个可以使用读取文件的InputStream。这是一个PITA,因为您无法查询(AFAIK)文件大小; 我在我的资产文件夹上运行一个预处理步骤,用它们各自的大小生成所有文件的列表,所以我可以知道,例如,要分配多大的缓冲区。

如果您的文件是资源,则可能需要通过Resource类才能访问它,尽pipe看起来资源也被打包到相同的资产包中。 不过,如上所述,Resource有一个openRawResource()调用来获取InputStream和一个openRawResourceFd()调用来获取文件描述符。

祝你好运。