Rya*_*heu 63 c file-io java-native-interface android-ndk
我出于性能原因使用Android NDK主要在C中创建应用程序,但似乎fopen等文件操作在Android中无法正常运行.每当我尝试使用这些功能时,应用程序崩溃.
如何使用Android NDK创建/写入文件?
Tim*_*ger 62
使用JNI,文件IO在Android上运行良好.也许您正在尝试使用错误路径打开文件而不检查返回代码?我修改了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)!");
}
Run Code Online (Sandbox Code Playgroud)
这是在我的手机上运行后的结果(带有SD卡):
$ adb -d shell cat /sdcard/hello.txt
HELLO WORLD!
Run Code Online (Sandbox Code Playgroud)
Ita*_*Ita 60
其他答案都是正确的.您可以使用FILE和通过NDK打开文件fopen,但不要忘记为其授予权限.
在Android清单中:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Run Code Online (Sandbox Code Playgroud)
小智 23
确保使用Java getExternalStorageDirectory()调用来获取SD卡的真实路径,因为较新的设备不会简单地将其映射到"/ sdcard".在这种情况下,尝试使用"/ sdcard"的硬编码位置将失败.
Som*_*Tim 21
我还可以验证fopen()是否正常工作,但是如果您尝试访问应用程序的资源或资源文件夹中的文件则不行.我建议,为了避免重新发明轮子,您要将应用程序附带的任何资产粘贴在assets文件夹中,然后将它们打包以进行分发.
在assets文件夹中,您需要执行以下两种操作之一,具体取决于文件是否由打包程序压缩.两者都使用AssetManager方法,您可以从context/app获取AssetManager.文件名总是相对于assets文件夹,顺便说一下:如果你的资源文件夹中有一个文件"foo.png",你打开"foo.png",而不是像"assets/foo.png"那样.
如果文件未被压缩(即,它是未被压缩的扩展之一,如.png),您可以从AssetManager.openFd()获取文件描述符并将其传递给C++.然后你可以使用fdopen(dup(fd),"r"); 将文件作为文件打开*.请注意,您必须fseek()到偏移量,并自己跟踪文件的长度.你真的得到了整个资产包的文件句柄,你感兴趣的文件只是一小部分.
如果您的文件是压缩的,则需要使用Java流阅读器:AssetManager.open()为您提供了一个可以使用读取文件的InputStream.这是一个PITA,因为您无法查询(AFAIK)文件大小; 我在我的资源文件夹上运行一个预处理步骤,生成一个包含各自大小的所有文件的列表,这样我就知道,例如,要分配多大的缓冲区.
如果您的文件是资源,您可能需要通过Resource类来访问它,尽管看起来资源也被打包到同一资产包中.如上所述,Resource有一个openRawResource()调用来获取InputStream和一个openRawResourceFd()调用来获取文件描述符.
祝好运.