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。

9 回复

好像鸿蒙NDK层无法直接访问 /data/app/ 等公共路径吧?这些路径属于ArkTS侧管理的沙箱环境,需通过特定接口传递文件描述符(fd)实现跨层操作。你提供的"No such file or directory"错误表明C层未找到文件,但ArkTS侧可正常访问,说明文件存在但路径权限或访问方式不兼容NDK层。试一下下面步骤:

ArkTS侧获取文件描述符,使用 @kit.CoreFileKitfileIo 接口打开文件并获取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


那请问有什么路径是可以在NDK层之间访问的呢?我不想调用ArkTs层。

我根据大家的提示总结出了问题原因,因为鸿蒙的应用软件都是在沙箱中运行的,沙箱中使用的是虚拟的硬盘,所以是无法直接访问真实硬盘上的文件,必须用沙箱中虚拟硬盘的路径来访问文件。

这个是真实硬盘的路径:

/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语言操作文件时,需要注意应用沙箱机制导致的路径访问限制。建议使用以下方法解决:

  1. 使用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);
}
  1. 获取正确的应用沙箱路径:
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);
  1. 确保已声明必要的权限: 在module.json5中添加:
"requestPermissions": [
    {
        "name": "ohos.permission.FILE_ACCESS"
    }
]
  1. 检查文件路径是否正确:
  • 使用绝对路径时,必须以/data/storage/el2开头
  • 确保文件已创建且权限正确
  1. 调试建议:
  • 先用OH_Access检查文件是否存在
  • 使用OH_GetError获取详细错误信息

注意:直接使用Linux标准路径(如/data/app)在NDK层不可访问,必须使用HarmonyOS提供的沙箱路径接口。

回到顶部