HarmonyOS 鸿蒙Next在NDK层用C语言如何打开文件?
HarmonyOS 鸿蒙Next在NDK层用C语言如何打开文件? 我在NDK层用C语言的open函数打开文件总是报“No such file or directory”,我要打开的文件是内部存储目录里的文件,比如:/data/app/el2/100/base/com.example.harmonytest/haps/entry/files/demo.txt,我用的是绝对路径,这个文件我在AskTS层是可以正常打开的,所以我想知道NDK层有没有办法操作文件?
HarmonyOS版本是5.1,OpenHarmony的API版本是19。
好像鸿蒙NDK层无法直接访问 /data/app/
等公共路径吧?这些路径属于ArkTS侧管理的沙箱环境,需通过特定接口传递文件描述符(fd)实现跨层操作。你提供的"No such file or directory"错误表明C层未找到文件,但ArkTS侧可正常访问,说明文件存在但路径权限或访问方式不兼容NDK层。试一下下面步骤:
ArkTS侧获取文件描述符,使用 @kit.CoreFileKit
的 fileIo
接口打开文件并获取fd:
import { fileIo as fs } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
let filePath = context.filesDir + "/demo.txt"; // 沙箱路径
let fd = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
将fd传递给NDK层,通过NAPI接口将fd传递给C层:
// 调用Native方法传递fd
testNapi.openFile(fd);
NDK层通过fd操作文件,在C代码中使用接收到的fd进行文件操作:
#include <fcntl.h>
#include <unistd.h>
napi_value OpenFile(napi_env env, napi_callback_info info) {
int fd;
napi_value argv;
napi_get_cb_info(env, info, nullptr, nullptr, argv, nullptr);
napi_get_value_int32(env, argv, &fd);
char buffer;
ssize_t len = read(fd, buffer, sizeof(buffer));
close(fd);
return nullptr;
}
更多关于HarmonyOS 鸿蒙Next在NDK层用C语言如何打开文件?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
我根据大家的提示总结出了问题原因,因为鸿蒙的应用软件都是在沙箱中运行的,沙箱中使用的是虚拟的硬盘,所以是无法直接访问真实硬盘上的文件,必须用沙箱中虚拟硬盘的路径来访问文件。
这个是真实硬盘的路径:
/data/app/el2/100/base/com.example.harmonytest/haps/entry/files/demo.txt
这个是沙箱虚拟硬盘的路径:
/data/storage/el2/base/haps/entry/files/demo.txt
使用鸿蒙NDK特定API
通过JNI获取文件路径
#include <jni.h>
#include <hilog/log.h>
// 鸿蒙日志宏
#define LOG_TAG "HarmonyFile"
#define LOGI(...) HILOG_INFO(LOG_APP, __VA_ARGS__)
#define LOGE(...) HILOG_ERROR(LOG_APP, __VA_ARGS__)
JNIEXPORT jint JNICALL
Java_com_example_harmony_MainAbility_openFileFromNDK(JNIEnv *env, jobject thiz, jstring filePath) {
const char *path = (*env)->GetStringUTFChars(env, filePath, 0);
FILE *file;
file = fopen(path, "r");
if (file == NULL) {
LOGE("无法打开文件: %s", path);
(*env)->ReleaseStringUTFChars(env, filePath, path);
return -1;
}
// 处理文件...
fclose(file);
(*env)->ReleaseStringUTFChars(env, filePath, path);
return 0;
}
可以试一下
楼主尝试一下将路径换位这样试试,前面加上前缀
file:///data/app/el2/100/base/com.example.harmonytest/haps/entry/files/demo.txt
非常感谢您的回答,但是很遗憾,我试了以下路径都还是报错:“No such file or directory”。
file:/data/app/el2/100/base/com.example.harmonytest/haps/entry/files/demo.txt
file://data/app/el2/100/base/com.example.harmonytest/haps/entry/files/demo.txt
file:///data/app/el2/100/base/com.example.harmonytest/haps/entry/files/demo.txt
不客气,开发者学堂里面有关于NDK的课程,你可以看看对你有没有帮助
https://developer.huawei.com/consumer/cn/training/course/live/C101730703861144394
在鸿蒙Next NDK层使用C语言打开文件,需调用POSIX标准的文件操作函数,通过open()
函数实现。函数原型为int open(const char *pathname, int flags, mode_t mode)
,其中pathname
为文件路径,flags
指定打开方式(如O_RDONLY
),mode
设置文件权限。成功时返回文件描述符,失败返回-1。需包含<fcntl.h>
头文件,并注意鸿蒙文件沙箱权限限制,确保路径位于应用可访问范围内。
在HarmonyOS Next的NDK层使用C语言操作文件时,需要注意应用沙箱机制导致的路径访问限制。建议使用以下方法解决:
- 使用OH_Open接口替代标准C的open函数:
#include <sys/stat.h>
#include <fcntl.h>
#include <hilog/log.h>
#include <stdlib.h>
int fd = OH_Open("/data/storage/el2/base/files/demo.txt", O_RDWR);
if (fd < 0) {
OH_LOG_ERROR(LOG_APP, "Open file failed: %{public}d", fd);
}
- 获取正确的应用沙箱路径:
char filePath[PATH_MAX] = {0};
if (OH_GetDataDirectory("/data/storage/el2/base/files/demo.txt", filePath, sizeof(filePath)) != 0) {
OH_LOG_ERROR(LOG_APP, "Get data directory failed");
}
int fd = OH_Open(filePath, O_RDWR);
- 确保已声明必要的权限: 在module.json5中添加:
"requestPermissions": [
{
"name": "ohos.permission.FILE_ACCESS"
}
]
- 检查文件路径是否正确:
- 使用绝对路径时,必须以/data/storage/el2开头
- 确保文件已创建且权限正确
- 调试建议:
- 先用OH_Access检查文件是否存在
- 使用OH_GetError获取详细错误信息
注意:直接使用Linux标准路径(如/data/app)在NDK层不可访问,必须使用HarmonyOS提供的沙箱路径接口。