OpenHarmony文件访问接口mod_fs模块解析
概述
mod_fs
模块是OpenHarmony文件访问接口的核心模块之一,位于interfaces/kits/js/src/mod_fs
目录下。该模块提供了完整的文件系统操作功能,包括文件读写、目录管理、文件监控、流处理等核心功能。本文将从目录结构、核心组件、接口设计、实现细节等多个维度进行深入解析。
目录结构分析
1. 核心文件
interfaces/kits/js/src/mod_fs/
├── module.cpp # 模块入口文件
├── common_func.h/.cpp # 通用功能函数
├── fs_utils.h/.cpp # 文件系统工具函数
└── properties/ # 属性接口实现
├── prop_n_exporter.h/.cpp
├── ani/ # 异步接口实现
└── [各种功能接口文件]
2. 类目录结构
├── class_file/ # 文件类实现
├── class_stat/ # 文件状态类实现
├── class_stream/ # 流处理类实现
├── class_atomicfile/ # 原子文件操作类
├── class_randomaccessfile/ # 随机访问文件类
├── class_readeriterator/ # 读取迭代器类
├── class_watcher/ # 文件监控类
└── class_tasksignal/ # 任务信号类
核心组件详解
1. 模块入口 (module.cpp)
module.cpp
是mod_fs模块的入口文件,负责:
- 模块注册:通过
napi_module_register
注册为"file.fs"模块 - 类型初始化:初始化各种枚举类型和常量
- 类导出:导出所有功能类到JavaScript环境
static napi_module _module = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Export,
.nm_modname = "file.fs",
.nm_priv = ((void *)0),
.reserved = {0}
};
导出的类型包括:
AccessModeType
:访问模式类型AccessFlagType
:访问标志类型LocationType
:位置类型(本地/云端)OpenMode
:打开模式WhenceType
:定位类型
2. 通用功能函数 (common_func.h/.cpp)
common_func
提供了模块的核心工具函数:
2.1 常量定义
// 文件打开标志
constexpr int RDONLY = UV_FS_O_RDONLY;
constexpr int WRONLY = UV_FS_O_WRONLY;
constexpr int RDWR = UV_FS_O_RDWR;
constexpr int CREATE = UV_FS_O_CREAT;
constexpr int TRUNC = UV_FS_O_TRUNC;
constexpr int APPEND = UV_FS_O_APPEND;
// 访问模式
constexpr unsigned int MODE_EXIST = 00;
constexpr unsigned int MODE_WRITE = 02;
constexpr unsigned int MODE_READ = 04;
constexpr unsigned int MODE_READ_WRITE = 06;
2.2 核心功能函数
文件信息结构体:
struct FileInfo {
bool isPath = false;
std::unique_ptr<char[]> path = { nullptr };
std::unique_ptr<DistributedFS::FDGuard> fdg = { nullptr };
};
主要功能函数:
ConvertJsFlags()
:转换JavaScript标志到系统标志InstantiateStat()
:实例化文件状态对象InstantiateFile()
:实例化文件对象InstantiateStream()
:实例化流对象GetReadArg()
:解析读取参数GetWriteArg()
:解析写入参数GetCopyPathArg()
:解析复制路径参数
3. 文件系统工具 (fs_utils.h/.cpp)
fs_utils
提供了文件系统相关的工具函数:
class FsUtils {
public:
static tuple<bool, size_t> GetActualLen(size_t bufLen, size_t bufOff,
const optional<int64_t> &length = nullopt);
static uint32_t ConvertFlags(const uint32_t &flags);
static void FsReqCleanup(uv_fs_t *req);
static string GetModeFromFlags(const uint32_t &flags);
static bool CheckPublicDirPath(const string &sandboxPath);
static string Decode(const string &uri);
};
类组件详解
1. File类 (class_file/)
File类提供了文件操作的核心功能,包含完整的文件实体管理和操作接口。
1.1 类结构设计
FileEntity结构体:
struct FileEntity {
std::unique_ptr<DistributedFS::FDGuard> fd_ = { nullptr };
std::string path_ = "";
std::string uri_ = "";
};
主要接口:
class FileNExporter final : public NExporter {
public:
static napi_value GetPath(napi_env env, napi_callback_info info);
static napi_value GetName(napi_env env, napi_callback_info info);
static napi_value GetParent(napi_env env, napi_callback_info info);
static napi_value Lock(napi_env env, napi_callback_info info);
static napi_value TryLock(napi_env env, napi_callback_info info);
static napi_value UnLock(napi_env env, napi_callback_info info);
static napi_value GetFD(napi_env env, napi_callback_info info);
};
1.2 核心实现细节
文件路径获取实现:
napi_value FileNExporter::GetPath(napi_env env, napi_callback_info info)
{
// 参数验证
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
// 获取文件实体
auto fileEntity = GetFileEntity(env, funcArg.GetThisVar());
if (!fileEntity) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
// 处理URI和路径
if (fileEntity->uri_.length() != 0) {
AppFileService::ModuleFileUri::FileUri fileUri(fileEntity->uri_);
return NVal::CreateUTF8String(env, fileUri.GetPath()).val_;
}
// 获取真实路径
auto [realPathRes, realPath] = RealPathCore(fileEntity->path_);
if (realPathRes != ERRNO_NOERR) {
NError(realPathRes).ThrowErr(env);
return nullptr;
}
return NVal::CreateUTF8String(env, string(static_cast<const char *>(realPath->ptr))).val_;
}
文件锁定机制实现:
napi_value FileNExporter::Lock(napi_env env, napi_callback_info info)
{
// 参数解析
bool exclusive = false;
if (!GetExclusive(env, funcArg, exclusive)) {
return nullptr;
}
// 异步执行回调
auto cbExec = [exclusive, fileEntity]() -> NError {
if (!fileEntity || !fileEntity->fd_.get()) {
return NError(EIO);
}
int ret = 0;
auto mode = exclusive ? LOCK_EX : LOCK_SH;
ret = flock(fileEntity->fd_.get()->GetFD(), mode);
if (ret < 0) {
return NError(errno);
}
return NError(ERRNO_NOERR);
};
// 支持Promise和Callback两种模式
if (funcArg.GetArgc() == NARG_CNT::ZERO ||
(funcArg.GetArgc() == NARG_CNT::ONE &&
!NVal(env, funcArg[NARG_POS::FIRST]).TypeIs(napi_function))) {
return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_LOCK_NAME, cbExec, cbCompl).val_;
} else {
return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_LOCK_NAME, cbExec, cbCompl).val_;
}
}
1.3 功能特性
- 文件路径管理:支持URI和本地路径两种模式
- 文件锁定机制:提供独占锁和共享锁支持
- 文件描述符获取:安全的FD管理
- 异步操作支持:Promise和Callback两种异步模式
- 内存管理:使用智能指针自动管理资源
2. Stat类 (class_stat/)
Stat类提供文件状态信息,包含完整的文件属性查询和类型判断功能。
2.1 类结构设计
StatEntity结构体:
struct StatEntity {
uv_stat_t stat_;
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
std::shared_ptr<FileInfo> fileInfo_;
#endif
};
主要接口:
class StatNExporter final : public NExporter {
public:
// 文件类型判断
static napi_value IsBlockDevice(napi_env env, napi_callback_info info);
static napi_value IsCharacterDevice(napi_env env, napi_callback_info info);
static napi_value IsDirectory(napi_env env, napi_callback_info info);
static napi_value IsFile(napi_env env, napi_callback_info info);
static napi_value IsSocket(napi_env env, napi_callback_info info);
static napi_value IsSymbolicLink(napi_env env, napi_callback_info info);
// 属性获取
static napi_value GetIno(napi_env env, napi_callback_info info);
static napi_value GetMode(napi_env env, napi_callback_info info);
static napi_value GetSize(napi_env env, napi_callback_info info);
static napi_value GetAtime(napi_env env, napi_callback_info info);
static napi_value GetMtime(napi_env env, napi_callback_info info);
static napi_value GetCtime(napi_env env, napi_callback_info info);
static napi_value GetAtimeNs(napi_env env, napi_callback_info info);
static napi_value GetMtimeNs(napi_env env, napi_callback_info info);
static napi_value GetCtimeNs(napi_env env, napi_callback_info info);
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
static napi_value GetLocation(napi_env env, napi_callback_info info);
#endif
};
2.2 核心实现细节
文件类型判断实现:
static napi_value CheckStatMode(napi_env env, napi_callback_info info, mode_t mode)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
HILOGE("Failed to get stat entity");
return nullptr;
}
bool check = (statEntity->stat_.st_mode & S_IFMT) == mode;
return NVal::CreateBool(env, check).val_;
}
napi_value StatNExporter::IsFile(napi_env env, napi_callback_info info)
{
return CheckStatMode(env, info, S_IFREG);
}
时间属性获取实现:
napi_value StatNExporter::GetAtimeNs(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
NError(UNKROWN_ERR).ThrowErr(env);
return nullptr;
}
return NVal::CreateBigIntUint64(env, static_cast<uint64_t>
(statEntity->stat_.st_atim.tv_sec * SECOND_TO_NANOSECOND +
statEntity->stat_.st_atim.tv_nsec)).val_;
}
云端位置获取实现:
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
napi_value StatNExporter::GetLocation(napi_env env, napi_callback_info info)
{
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
std::unique_ptr<char[]> value = CreateUniquePtr<char[]>(MAX_ATTR_NAME);
if (value == nullptr) {
NError(ENOMEM).ThrowErr(env);
return nullptr;
}
ssize_t size = 0;
if (statEntity->fileInfo_->isPath) {
size = getxattr(statEntity->fileInfo_->path.get(),
CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME);
} else {
size = fgetxattr(statEntity->fileInfo_->fdg->GetFD(),
CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME);
}
Location defaultLocation = LOCAL;
if (size <= 0) {
if (errno != ENODATA && errno != EOPNOTSUPP) {
HILOGE("Getxattr value failed, errno is %{public}d", errno);
}
return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
}
std::string location = string(value.get(), static_cast<size_t>(size));
if (!std::all_of(location.begin(), location.end(), ::isdigit)) {
HILOGE("Getxattr location is not all digit!");
return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
}
defaultLocation = static_cast<Location>(atoi(location.c_str()));
return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
}
#endif
2.3 功能特性
- 文件类型判断:支持7种文件类型检测
- 属性获取:提供完整的文件属性信息
- 时间精度:支持秒级和纳秒级时间获取
- 云端支持:支持云端文件位置检测
- 跨平台兼容:针对不同平台的条件编译
3. Stream类 (class_stream/)
Stream类提供流式文件操作,支持高效的流式读写和异步处理。
3.1 类结构设计
StreamEntity结构体:
struct StreamEntity {
std::shared_ptr<FILE> fp{ nullptr };
};
主要接口:
class StreamNExporter final : public NExporter {
public:
static napi_value WriteSync(napi_env env, napi_callback_info cbInfo);
static napi_value Flush(napi_env env, napi_callback_info cbInfo);
static napi_value FlushSync(napi_env env, napi_callback_info cbInfo);
static napi_value ReadSync(napi_env env, napi_callback_info cbInfo);
static napi_value CloseSync(napi_env env, napi_callback_info cbInfo);
static napi_value Write(napi_env env, napi_callback_info cbInfo);
static napi_value Read(napi_env env, napi_callback_info cbInfo);
static napi_value Close(napi_env env, napi_callback_info cbInfo);
static napi_value Seek(napi_env env, napi_callback_info cbInfo);
};
3.2 核心实现细节
流式写入实现:
napi_value StreamNExporter::WriteSync(napi_env env, napi_callback_info cbInfo)
{
NFuncArg funcArg(env, cbInfo);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
auto streamEntity = GetEntityOf(env, funcArg);
if (streamEntity == nullptr) {
NError(UNKROWN_ERR).ThrowErr(env);
return nullptr;
}
auto fp = GetFilePtr(streamEntity);
if (fp == nullptr) {
NError(EIO).ThrowErr(env);
return nullptr;
}
// 解析写入参数
auto [succ, bufGuard, buf, len, offset] =
CommonFunc::GetWriteArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
if (!succ) {
return nullptr;
}
// 设置文件偏移
if (offset >= 0) {
int ret = fseek(fp.get(), static_cast<long>(offset), SEEK_SET);
if (ret < 0) {
NError(errno).ThrowErr(env);
return nullptr;
}
}
// 执行写入
size_t writeLen = fwrite(buf, 1, len, fp.get());
if ((writeLen == 0) && (writeLen != len)) {
NError(EIO).ThrowErr(env);
return nullptr;
}
return NVal::CreateInt64(env, static_cast<int64_t>(writeLen)).val_;
}
异步读取实现:
static napi_value ReadExec(napi_env env, NFuncArg &funcArg, shared_ptr<FILE> fp)
{
auto [succ, buf, len, offset] =
CommonFunc::GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
if (!succ) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
auto arg = CreateSharedPtr<AsyncReadArg>(NVal(env, funcArg[NARG_POS::FIRST]));
if (arg == nullptr) {
NError(ENOMEM).ThrowErr(env);
return nullptr;
}
// 异步执行回调
auto cbExec = [arg, buf = buf, len = len, fp, offset = offset]() -> NError {
if (!fp.get()) {
return NError(EIO);
}
if (offset >= 0) {
if (fseek(fp.get(), static_cast<long>(offset), SEEK_SET) < 0) {
return NError(errno);
}
}
size_t actLen = fread(buf, 1, len, fp.get());
if ((actLen != static_cast<size_t>(len) && !feof(fp.get())) || ferror(fp.get())) {
return NError(EIO);
} else {
arg->lenRead = actLen;
return NError(ERRNO_NOERR);
}
};
auto cbCompl = [arg](napi_env env, NError err) -> NVal {
if (err) {
return { env, err.GetNapiErr(env) };
}
return { NVal::CreateInt64(env, arg->lenRead) };
};
// 支持Promise和Callback模式
NVal thisVar(env, funcArg.GetThisVar());
if (funcArg.GetArgc() == NARG_CNT::ONE ||
(funcArg.GetArgc() == NARG_CNT::TWO &&
!NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) {
return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_STREAM_READ_NAME, cbExec, cbCompl).val_;
} else {
int cbIdx = ((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD);
NVal cb(env, funcArg[cbIdx]);
return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_STREAM_READ_NAME, cbExec, cbCompl).val_;
}
}
文件定位实现:
napi_value StreamNExporter::Seek(napi_env env, napi_callback_info cbInfo)
{
NFuncArg funcArg(env, cbInfo);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
auto streamEntity = GetEntityOf(env, funcArg);
if (streamEntity == nullptr) {
NError(UNKROWN_ERR).ThrowErr(env);
return nullptr;
}
auto fp = GetFilePtr(streamEntity);
if (fp == nullptr) {
NError(EIO).ThrowErr(env);
return nullptr;
}
// 获取偏移量
auto [succGetOffset, offset] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt64();
if (!succGetOffset) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
// 获取定位类型
int whence = SEEK_SET;
if (funcArg.GetArgc() == NARG_CNT::TWO) {
auto [succGetWhence, pos] = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32(SEEK_SET);
if (!succGetWhence || pos < SEEK_SET || pos > SEEK_END) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
whence = pos;
}
// 执行定位
if (offset >= 0) {
int ret = fseek(fp.get(), static_cast<long>(offset), whence);
if (ret < 0) {
NError(errno).ThrowErr(env);
return nullptr;
}
}
// 返回当前位置
int64_t res = ftell(fp.get());
if (res < 0) {
NError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateInt64(env, res).val_;
}
3.3 功能特性
- 流式读写操作:基于标准C库FILE*的高效流操作
- 异步处理支持:完整的Promise和Callback异步模式
- 缓冲区管理:智能的缓冲区参数解析和管理
- 错误处理机制:完善的错误检查和异常处理
- 线程安全:使用互斥锁保护关键操作
- 内存管理:智能指针自动管理资源生命周期
4. AtomicFile类 (class_atomicfile/)
AtomicFile类提供原子文件操作:
功能特点:
- 原子性写入保证
- 事务性操作支持
- 数据一致性保护
5. RandomAccessFile类 (class_randomaccessfile/)
RandomAccessFile类提供随机访问文件操作:
核心功能:
- 随机位置读写
- 文件指针管理
- 高效的数据访问
6. ReaderIterator类 (class_readeriterator/)
ReaderIterator类提供文件读取迭代器:
主要特性:
- 迭代式文件读取
- 内存效率优化
- 大数据文件处理
7. Watcher类 (class_watcher/)
Watcher类提供文件系统监控功能:
监控功能:
- 文件变化监听
- 目录监控
- 事件回调机制
- 实时通知支持
8. TaskSignal类 (class_tasksignal/)
TaskSignal类提供任务信号处理:
信号功能:
- 任务状态管理
- 信号传递机制
- 异步任务协调
Properties目录详解
Properties目录包含了大量的文件操作接口实现,每个接口都有对应的同步和异步版本,以及核心实现和包装层。
1. 核心文件操作接口
1.1 文件打开接口 (open.cpp)
同步打开实现:
napi_value Open::Sync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
// 解析路径参数
auto [succPath, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8StringPath();
if (!succPath) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
// 解析打开模式
auto [succMode, mode] = GetJsFlags(env, funcArg);
if (!succMode) {
return nullptr;
}
string pathStr(path.get());
// 处理URI路径
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
if (pathStr.find("://") != string::npos) {
auto [res, uriStr] = OpenFileByUri(pathStr, mode);
if (res < 0) {
NError(res).ThrowErr(env);
return nullptr;
}
return InstantiateFile(env, res, uriStr, true).val_;
}
#endif
// 处理普通路径
int ret = OpenFileByPath(pathStr, mode);
if (ret < 0) {
NError(ret).ThrowErr(env);
return nullptr;
}
return InstantiateFile(env, ret, pathStr, false).val_;
}
异步打开实现:
napi_value Open::Async(napi_env env, napi_callback_info info)
{
// 参数解析
auto [succPath, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8StringPath();
auto [succMode, mode] = GetJsFlags(env, funcArg);
// 创建异步参数
auto arg = CreateSharedPtr<AsyncOpenFileArg>();
if (arg == nullptr) {
NError(ENOMEM).ThrowErr(env);
return nullptr;
}
// 异步执行回调
auto cbExec = [arg, path = string(path.get()), mode = mode]() -> NError {
return AsyncCbExec(arg, path, mode);
};
// 完成回调
auto cbCompl = [arg](napi_env env, NError err) -> NVal {
if (err) {
return { env, err.GetNapiErr(env) };
}
if (arg->path.empty() && arg->uri.size()) {
return InstantiateFile(env, arg->fd, arg->uri, true, true);
}
return InstantiateFile(env, arg->fd, arg->path, false, true);
};
// 支持Promise和Callback模式
NVal thisVar(env, funcArg.GetThisVar());
if (funcArg.GetArgc() == NARG_CNT::ONE ||
(funcArg.GetArgc() == NARG_CNT::TWO &&
!NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) {
return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_OPEN_NAME, cbExec, cbCompl).val_;
} else {
int cbIdx = ((funcArg.GetArgc() == NARG_CNT::THREE) ? NARG_POS::THIRD : NARG_POS::SECOND);
NVal cb(env, funcArg[cbIdx]);
return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_OPEN_NAME, cbExec, cbCompl).val_;
}
}
1.2 文件读取接口 (read_core.cpp)
核心读取实现:
FsResult<int64_t> ReadCore::DoRead(const int32_t &fd, ArrayBuffer &arrayBuffer,
const optional<ReadOptions> &options)
{
if (fd < 0) {
return FsResult<int64_t>::Error(EINVAL);
}
// 验证读取参数
auto [succ, buf, len, offset] = ValidReadArg(arrayBuffer, options);
if (!succ) {
return FsResult<int64_t>::Error(EINVAL);
}
// 创建libuv读取请求
uv_buf_t buffer = uv_buf_init(static_cast<char *>(buf), static_cast<uint32_t>(len));
unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> readReq = {
new uv_fs_t, FsUtils::FsReqCleanup };
if (!readReq) {
return FsResult<int64_t>::Error(ENOMEM);
}
// 执行异步读取
int ret = uv_fs_read(nullptr, readReq.get(), fd, &buffer, 1, offset, nullptr);
if (ret < 0) {
return FsResult<int64_t>::Error(ret);
}
return FsResult<int64_t>::Success(static_cast<int64_t>(ret));
}
1.3 文件写入接口 (write_core.cpp)
核心写入实现:
FsResult<int64_t> WriteCore::DoWrite(const int32_t fd, void *buf, const size_t len,
const int64_t offset)
{
// 创建libuv写入请求
uv_buf_t buffer = uv_buf_init(static_cast<char *>(buf), static_cast<unsigned int>(len));
unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> writeReq = {
new uv_fs_t, FsUtils::FsReqCleanup };
if (!writeReq) {
return FsResult<int64_t>::Error(ENOMEM);
}
// 执行异步写入
int ret = uv_fs_write(nullptr, writeReq.get(), fd, &buffer, 1, offset, nullptr);
if (ret < 0) {
return FsResult<int64_t>::Error(ret);
}
return FsResult<int64_t>::Success(static_cast<int64_t>(ret));
}
1.4 文件状态接口 (stat.cpp)
同步状态获取:
napi_value Stat::Sync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE)) {
NError(EINVAL).ThrowErr(env);
return nullptr;
}
// 解析文件参数(路径或文件描述符)
auto [succ, fileInfo] = ParseJsFile(env, funcArg[NARG_POS::FIRST]);
if (!succ) {
return nullptr;
}
// 创建libuv状态请求
std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> stat_req = {
new (std::nothrow) uv_fs_t, CommonFunc::fs_req_cleanup };
if (!stat_req) {
NError(ENOMEM).ThrowErr(env);
return nullptr;
}
// 执行状态检查
auto err = CheckFsStat(fileInfo, stat_req.get());
if (err) {
err.ThrowErr(env);
return nullptr;
}
// 实例化Stat对象
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
auto arg = CreateSharedPtr<FileInfo>(move(fileInfo));
if (arg == nullptr) {
NError(ENOMEM).ThrowErr(env);
return nullptr;
}
auto stat = CommonFunc::InstantiateStat(env, stat_req->statbuf, arg).val_;
#else
auto stat = CommonFunc::InstantiateStat(env, stat_req->statbuf).val_;
#endif
return stat;
}
2. 高级功能接口
文件基础操作:
open.cpp/.h
:文件打开(支持URI和本地路径)close.cpp/.h
:文件关闭read_core.cpp/.h
:文件读取核心实现write_core.cpp/.h
:文件写入核心实现lseek.cpp/.h
:文件定位
目录操作:
mkdir.cpp/.h
:创建目录rmdir.cpp/.h
:删除目录listfile.cpp/.h
:列出文件
文件管理:
copy.cpp/.h
:文件复制move.cpp/.h
:文件移动rename.cpp/.h
:文件重命名unlink.cpp/.h
:删除文件
流处理:
create_stream.cpp/.h
:创建流fdopen_stream.cpp/.h
:从文件描述符创建流
文件监控:
watcher.cpp/.h
:文件监控
扩展属性:
xattr.cpp/.h
:扩展属性操作
同步操作:
fsync.cpp/.h
:强制同步fdatasync.cpp/.h
:数据同步
3. 异步接口实现 (ani目录)
每个功能都有对应的异步实现,位于ani
子目录中:
异步接口特点:
- 非阻塞操作:使用libuv进行异步I/O操作
- 回调机制:支持Promise和Callback两种异步模式
- 错误处理:完善的异步错误处理机制
- 进度通知:支持操作进度回调
- 内存管理:异步操作中的智能内存管理
技术架构特点
1. 分层架构设计
mod_fs模块采用了清晰的分层架构:
JavaScript API层
↓
NAPI接口层 (NExporter)
↓
业务逻辑层 (Entity类)
↓
系统调用层 (libuv/系统API)
2. 异步处理机制
模块大量使用libuv进行异步I/O操作:
// 异步操作示例
static void AsyncCallback(uv_fs_t* req) {
// 处理异步操作结果
uv_fs_req_cleanup(req);
}
3. 内存管理
使用智能指针进行内存管理:
std::unique_ptr<DistributedFS::FDGuard> fdg;
std::unique_ptr<char[]> path;
4. 错误处理
统一的错误处理机制:
NError(EINVAL).ThrowErr(env);
平台兼容性
1. 平台特定代码
模块通过宏定义处理不同平台的差异:
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
// 非Windows和非iOS平台的特定代码
#endif
#ifndef WIN_PLATFORM
// 非Windows平台的特定代码
#endif
2. 条件编译
根据平台特性进行条件编译:
#ifdef WIN_PLATFORM
string nExporterName = product->GetNExporterName();
#else
string nExporterName = product->GetClassName();
#endif
性能优化
1. 异步I/O
大量使用异步I/O操作,避免阻塞主线程:
uv_fs_open(loop, req, path, flags, mode, AsyncCallback);
2. 内存池管理
使用FDGuard进行文件描述符的自动管理:
auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(fd, false);
3. 缓冲区优化
针对不同操作类型优化缓冲区使用:
tuple<bool, void *, size_t, int64_t> GetReadArg(napi_env env,
napi_value readBuf,
napi_value option);
安全特性
1. 权限检查
bool CheckPublicDirPath(const std::string &sandboxPath);
2. 用户ID验证
bool GetAndCheckUserId(Uri* uri, std::string &userId);
3. 系统应用检查
bool IsSystemApp();
使用示例
1. 基本文件操作
import fs from '@ohos.file.fs';
// 打开文件
let file = fs.openSync('/path/to/file', fs.OpenMode.READ_ONLY);
// 读取文件
let buffer = new ArrayBuffer(1024);
let bytesRead = fs.readSync(file.fd, buffer);
// 关闭文件
fs.closeSync(file.fd);
2. 异步文件操作
import fs from '@ohos.file.fs';
// 异步读取
fs.read(file.fd, buffer, (err, bytesRead) => {
if (err) {
console.error('Read failed:', err);
return;
}
console.log('Bytes read:', bytesRead);
});
3. 文件监控
import fs from '@ohos.file.fs';
// 创建文件监控器
let watcher = fs.createWatcher('/path/to/watch');
// 监听文件变化
watcher.on('change', (event) => {
console.log('File changed:', event);
});
4. 流式操作
import fs from '@ohos.file.fs';
// 创建流
let stream = fs.createStream(file.fd);
// 流式写入
let data = "Hello, World!";
let bytesWritten = stream.writeSync(data);
// 流式读取
let buffer = new ArrayBuffer(1024);
let bytesRead = stream.readSync(buffer);
// 关闭流
stream.closeSync();
5. 文件状态查询
import fs from '@ohos.file.fs';
// 获取文件状态
let stat = fs.statSync('/path/to/file');
// 检查文件类型
if (stat.isFile()) {
console.log('This is a file');
}
// 获取文件大小
console.log('File size:', stat.size);
// 获取修改时间
console.log('Modified time:', stat.mtime);
6. 文件锁定
import fs from '@ohos.file.fs';
// 打开文件
let file = fs.openSync('/path/to/file', fs.OpenMode.READ_WRITE);
// 获取独占锁
file.lock(true, (err) => {
if (err) {
console.error('Lock failed:', err);
return;
}
console.log('File locked successfully');
// 执行需要独占访问的操作
// ...
// 释放锁
file.unlock();
});
7. 云端文件操作
import fs from '@ohos.file.fs';
// 打开云端文件
let cloudFile = fs.openSync('file://media/image/123', fs.OpenMode.READ_ONLY);
// 获取文件状态(包含云端位置信息)
let stat = fs.statSync(cloudFile.fd);
console.log('File location:', stat.location); // LOCAL or CLOUD
// 获取文件路径
console.log('File path:', cloudFile.path);
console.log('File name:', cloudFile.name);
console.log('Parent directory:', cloudFile.getParent());
总结
mod_fs模块是OpenHarmony文件访问接口的核心组件,提供了完整的文件系统操作功能。其设计具有以下特点:
- 模块化设计:清晰的目录结构和组件分离
- 异步优先:大量使用异步I/O提高性能
- 平台兼容:支持多平台的条件编译
- 安全可靠:完善的权限检查和错误处理
- 易于使用:简洁的JavaScript API接口