OpenHarmony文件访问接口mod_file模块
概述
mod_file模块是OpenHarmony分布式文件系统(DistributedFS)中负责文件操作的核心JavaScript接口模块。该模块基于Node-API(NAPI)技术,为JavaScript应用提供了完整的文件系统操作能力,包括文件/目录的创建、删除、复制、移动、读写等基础功能。
模块架构
1. 文件组织结构
interfaces/kits/js/src/mod_file/
├── module.cpp # 模块入口文件
├── common_func.h/.cpp # 通用工具函数
└── class_file/ # File类实现
├── file_n_exporter.h # 接口定义头文件
└── file_n_exporter.cpp # 核心实现文件(1454行)
2. 核心组件
2.1 模块入口(module.cpp)
static napi_value Export(napi_env env, napi_value exports)
{
std::vector<unique_ptr<NExporter> > products;
products.emplace_back(make_unique<FileNExporter>(env, exports));
for (auto &&product : products) {
if (!product->Export()) {
HILOGE("INNER BUG. Failed to export class %{public}s for module file",
product->GetClassName().c_str());
return nullptr;
}
}
return exports;
}
NAPI_MODULE(file, Export)
模块采用工厂模式,通过FileNExporter
类导出所有文件操作接口。
2.2 通用工具函数(common_func)
struct CommonFunc {
static std::tuple<bool, napi_ref, napi_ref, napi_ref>
GetCallbackHandles(napi_env env, napi_value object);
};
提供统一的回调函数处理机制,支持success、fail、complete三种回调类型。
接口设计
1. 导出的API接口
mod_file模块共导出12个核心API:
接口名称 | 功能描述 | 参数类型 |
---|---|---|
mkdir |
创建目录 | {uri: string, recursive: boolean} |
rmdir |
删除目录 | {uri: string, recursive: boolean} |
get |
获取文件/目录信息 | {uri: string, recursive: boolean} |
list |
列出目录内容 | {uri: string} |
copy |
复制文件/目录 | {srcUri: string, dstUri: string} |
move |
移动文件/目录 | {srcUri: string, dstUri: string} |
delete |
删除文件/目录 | {uri: string} |
access |
检查文件/目录访问权限 | {uri: string} |
writeText |
写入文本内容 | {uri: string, text: string, append: boolean} |
writeArrayBuffer |
写入二进制数据 | {uri: string, buffer: ArrayBuffer, position: number, append: boolean} |
readText |
读取文本内容 | {uri: string} |
readArrayBuffer |
读取二进制数据 | {uri: string, length: number, position: number} |
2. 数据结构定义
2.1 文件信息结构
struct FileInfo {
int32_t length = 0; // 文件大小
int64_t lastModifiedTime = 0; // 最后修改时间
std::string type = ""; // 文件类型(file/dir)
std::string uri = ""; // 文件URI
};
2.2 异步回调信息结构
每种操作都有对应的异步回调信息结构,以AsyncMkdirCallbackInfo
为例:
struct AsyncMkdirCallbackInfo {
napi_env env = nullptr; // NAPI环境
napi_async_work asyncWork = nullptr; // 异步工作句柄
napi_ref callback[3] = { 0 }; // 回调函数引用数组
bool recursive = false; // 是否递归创建
std::string url = ""; // 目标路径
int result = DEFAULT_RESULT; // 操作结果
int errorType = -1; // 错误类型
};
核心实现机制
1. 异步操作模式
所有文件操作都采用异步模式,遵循以下流程:
- 参数解析:从JavaScript传入的参数中提取必要信息
- URI验证:通过
CheckUri
函数验证路径合法性 - 异步工作创建:使用
napi_create_async_work
创建异步任务 - 执行函数:在后台线程执行实际的文件操作
- 完成回调:将结果通过回调函数返回给JavaScript
2. 关键实现函数
2.1 URI验证机制
bool CheckUri(napi_env env, string &path)
{
// 检查路径长度限制
if (path.length() > PATH_MAX) {
return false;
}
// 检查路径格式和权限
// 实现路径安全验证逻辑
return true;
}
2.2 文件操作核心函数
目录创建(MkdirExec):
void MkdirExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncMkdirCallbackInfo *)data;
string path = asyncCallbackInfo->url;
asyncCallbackInfo->result = FAILED;
asyncCallbackInfo->errorType = FILE_IO_ERROR;
if (GetRealPath(path) == ENOENT) {
path = UriToAbsolute(path);
if (asyncCallbackInfo->recursive && Mkdirs(path)) {
asyncCallbackInfo->result = SUCCESS;
} else if (mkdir(path.c_str(), DIR_FAULT_PERM) != FAILED) {
asyncCallbackInfo->result = SUCCESS;
}
}
}
文件复制(CopyExec):
void CopyExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncCopyCallbackInfo *)data;
string path = asyncCallbackInfo->url;
string pathDst = asyncCallbackInfo->urlDst;
asyncCallbackInfo->result = FAILED;
asyncCallbackInfo->errorType = FILE_IO_ERROR;
if (GetRealPath(path) == ENOENT) {
asyncCallbackInfo->errorType = FILE_PATH_ERROR;
return;
}
struct stat statbf;
if (stat(path.c_str(), &statbf) == FAILED) {
asyncCallbackInfo->errorType = FILE_IO_ERROR;
return;
}
int retval;
if (S_ISREG(statbf.st_mode)) {
retval = FileCopy(path, pathDst); // 文件复制
} else if (S_ISDIR(statbf.st_mode)) {
retval = DirCopy(path, pathDst); // 目录复制
}
if (retval == SUCCESS) {
asyncCallbackInfo->result = SUCCESS;
} else {
asyncCallbackInfo->errorType = retval;
}
}
文件移动(MoveExec):
void MoveExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncMoveCallbackInfo *)data;
string path = asyncCallbackInfo->url;
string pathDst = asyncCallbackInfo->urlDst;
asyncCallbackInfo->result = FAILED;
asyncCallbackInfo->errorType = FILE_IO_ERROR;
if (GetRealPath(path) == ENOENT) {
asyncCallbackInfo->errorType = FILE_PATH_ERROR;
return;
}
struct stat statbf;
if (stat(path.c_str(), &statbf) == FAILED) {
asyncCallbackInfo->errorType = FILE_IO_ERROR;
return;
}
if (S_ISREG(statbf.st_mode)) {
int retval = FileCopy(path, pathDst);
if (retval == SUCCESS) {
if (remove(path.c_str()) == SUCCESS) {
asyncCallbackInfo->result = SUCCESS;
}
} else {
asyncCallbackInfo->errorType = retval;
}
} else if (S_ISDIR(statbf.st_mode)) {
int retval = DirCopy(path, pathDst);
if (retval == SUCCESS) {
if (Rmdirs(path)) {
asyncCallbackInfo->result = SUCCESS;
}
} else {
asyncCallbackInfo->errorType = retval;
}
}
}
文件删除(DeleteExec):
void DeleteExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncDeleteCallbackInfo *)data;
string path = asyncCallbackInfo->url;
asyncCallbackInfo->result = FAILED;
int statPath = GetRealPath(path);
if (statPath == ENOENT) {
asyncCallbackInfo->errorType = FILE_PATH_ERROR;
} else if (statPath == COMMON_NUM::ZERO && remove(path.c_str()) != FAILED) {
asyncCallbackInfo->result = SUCCESS;
} else {
asyncCallbackInfo->errorType = FILE_IO_ERROR;
}
}
文本写入(WriteTextExec):
void WriteTextExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncWriteCallbackInfo *)data;
string path = asyncCallbackInfo->url;
string text = asyncCallbackInfo->text;
asyncCallbackInfo->result = FAILED;
asyncCallbackInfo->errorType = FILE_IO_ERROR;
int fd = -1;
int statPath = GetRealPath(path);
if (statPath == COMMON_NUM::ZERO || statPath == ENOENT) {
if (asyncCallbackInfo->append) {
fd = open(path.c_str(), O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
} else {
fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
}
if (fd != FAILED) {
if (write(fd, text.c_str(), text.length()) != FAILED) {
asyncCallbackInfo->result = SUCCESS;
}
close(fd);
}
} else {
asyncCallbackInfo->errorType = FILE_IO_ERROR;
}
}
二进制数据写入(WriteArrayBufferExec):
void WriteArrayBufferExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncWriteBufferCallbackInfo *)data;
string path = asyncCallbackInfo->url;
asyncCallbackInfo->result = FAILED;
asyncCallbackInfo->errorType = FILE_IO_ERROR;
int fd = -1;
int statPath = GetRealPath(path);
if (statPath == COMMON_NUM::ZERO || statPath == ENOENT) {
if (asyncCallbackInfo->append) {
fd = open(path.c_str(), O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
} else {
fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
lseek(fd, asyncCallbackInfo->position, SEEK_CUR);
}
if (fd != FAILED) {
if (write(fd, asyncCallbackInfo->buffer, asyncCallbackInfo->len) != FAILED) {
asyncCallbackInfo->result = SUCCESS;
}
close(fd);
}
} else {
asyncCallbackInfo->errorType = FILE_IO_ERROR;
}
}
文本读取(ReadTextExec):
void ReadTextExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncReadCallbackInfo *)data;
string path = asyncCallbackInfo->url;
asyncCallbackInfo->result = FAILED;
asyncCallbackInfo->errorType = FILE_IO_ERROR;
int statPath = GetRealPath(path);
if (statPath == COMMON_NUM::ZERO) {
FDGuard fdg;
fdg.SetFD(open(path.c_str(), O_RDONLY));
struct stat buf;
int result = stat(path.c_str(), &buf);
if (fdg.GetFD() != FAILED && result != FAILED) {
auto buffer = std::make_unique<char[]>(buf.st_size + 1);
if (buffer == nullptr) {
UniError(ENOMEM).ThrowErr(env);
return;
}
if (read(fdg.GetFD(), buffer.get(), buf.st_size) != FAILED) {
asyncCallbackInfo->result = SUCCESS;
asyncCallbackInfo->text = std::string(buffer.get());
}
}
} else {
asyncCallbackInfo->errorType = FILE_PATH_ERROR;
}
}
二进制数据读取(ReadArrayBufferExec):
void ReadArrayBufferExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncReadBufferCallbackInfo *)data;
string path = asyncCallbackInfo->url;
asyncCallbackInfo->result = FAILED;
asyncCallbackInfo->errorType = FILE_IO_ERROR;
int statPath = GetRealPath(path);
if (statPath == COMMON_NUM::ZERO) {
FDGuard fdg;
fdg.SetFD(open(path.c_str(), O_RDONLY));
struct stat buf;
int result = stat(path.c_str(), &buf);
if (fdg.GetFD() != FAILED && result != FAILED) {
int32_t begin = (buf.st_size < asyncCallbackInfo->position) ?
buf.st_size : asyncCallbackInfo->position;
int32_t len = (asyncCallbackInfo->length == COMMON_NUM::ZERO) ?
(buf.st_size - begin) : asyncCallbackInfo->length;
auto buffer = std::make_unique<char[]>(len + 1);
if (buffer == nullptr) {
UniError(ENOMEM).ThrowErr(env);
return;
}
lseek(fdg.GetFD(), begin, SEEK_CUR);
if (read(fdg.GetFD(), buffer.get(), len) != FAILED) {
asyncCallbackInfo->result = SUCCESS;
asyncCallbackInfo->len = len;
asyncCallbackInfo->contents = std::string(buffer.get());
}
}
} else {
asyncCallbackInfo->errorType = FILE_PATH_ERROR;
}
}
目录删除(RmdirExec):
void RmdirExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncRmdirCallbackInfo *)data;
string path = asyncCallbackInfo->url;
asyncCallbackInfo->result = FAILED;
asyncCallbackInfo->errorType = FILE_IO_ERROR;
int statPath = GetRealPath(path);
if (statPath == COMMON_NUM::ZERO) {
if (asyncCallbackInfo->recursive && Rmdirs(path)) {
asyncCallbackInfo->result = SUCCESS;
} else if (remove(path.c_str()) != FAILED) {
asyncCallbackInfo->result = SUCCESS;
}
} else if (statPath == ENOENT) {
asyncCallbackInfo->errorType = FILE_PATH_ERROR;
}
}
文件访问权限检查(AccessExec):
void AccessExec(napi_env env, void *data)
{
auto *asyncCallbackInfo = (AsyncAccessCallbackInfo *)data;
string path = asyncCallbackInfo->url;
asyncCallbackInfo->result = FAILED;
int statPath = GetRealPath(path);
if (statPath == ENOENT) {
asyncCallbackInfo->errorType = FILE_PATH_ERROR;
} else if (statPath == COMMON_NUM::ZERO) {
asyncCallbackInfo->result = SUCCESS;
} else {
asyncCallbackInfo->errorType = FILE_IO_ERROR;
}
}
2.3 辅助工具函数
递归目录创建(Mkdirs):
bool Mkdirs(string path)
{
for (size_t i = 1; i < path.length(); ++i) {
if (path[i] == '/') {
path[i] = '\0';
if (access(path.c_str(), 0) != 0 && mkdir(path.c_str(), DIR_FAULT_PERM) == FAILED) {
return false;
}
path[i] = '/';
}
}
if (path.length() <= 0 || access(path.c_str(), 0) == 0 || mkdir(path.c_str(), DIR_FAULT_PERM) == FAILED) {
return false;
}
return true;
}
递归目录删除(Rmdirs):
bool Rmdirs(const string &path)
{
DIR *pDir;
struct dirent *ptr = nullptr;
if (!(pDir = opendir(path.c_str()))) {
return false;
}
while ((ptr = readdir(pDir)) != nullptr) {
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
if ((ptr->d_type == DT_DIR && Rmdirs(path + "/" + ptr->d_name)) ||
remove((path + "/" + ptr->d_name).c_str()) == 0) {
} else {
closedir(pDir);
return false;
}
}
}
closedir(pDir);
if (rmdir(path.c_str()) != 0) {
return false;
}
return true;
}
文件复制(FileCopy):
int FileCopy(const string& srcPath, const string& dstPath)
{
bool ret = FILE_IO_ERROR;
string src = srcPath;
string dest = dstPath;
if (GetRealPath(src) == 0) {
if (GetRealPath(dest) == ENOENT) {
FDGuard sfd;
sfd.SetFD(open(src.c_str(), O_RDONLY));
struct stat attrSrc;
if (stat(src.c_str(), &attrSrc) == FAILED) {
return FILE_IO_ERROR;
}
dest = UriToAbsolute(dest);
FDGuard ofd;
ofd.SetFD(open(dest.c_str(), O_WRONLY | O_CREAT, attrSrc.st_mode));
if (ofd.GetFD() != FAILED) {
ssize_t bytes = sendfile(ofd.GetFD(), sfd.GetFD(), nullptr, attrSrc.st_size);
if (bytes == attrSrc.st_size) {
ret = SUCCESS;
}
}
}
}
return ret;
}
目录复制(DirCopy):
int DirCopy(const string& srcPath, const string& dstPath)
{
string src = srcPath;
string dest = dstPath;
if (GetRealPath(src) == ENOENT) {
return FILE_PATH_ERROR;
}
if (GetRealPath(dest) == ENOENT) {
struct stat attrSrc;
if (stat(src.c_str(), &attrSrc) == FAILED || !S_ISDIR(attrSrc.st_mode)) {
return FILE_IO_ERROR;
}
dest = UriToAbsolute(dest);
if (mkdir(dest.c_str(), attrSrc.st_mode) == FAILED) {
return FILE_IO_ERROR;
}
// 递归复制目录内容
// ... 实现细节
}
return SUCCESS;
}
3. 错误处理机制
3.1 错误类型定义
constexpr int SUCCESS = 0; // 操作成功
constexpr int FAILED = -1; // 操作失败
constexpr int URI_PARAMER_ERROR = 202; // URI参数错误
constexpr int FILE_IO_ERROR = 300; // 文件IO错误
constexpr int FILE_PATH_ERROR = 301; // 文件路径错误
3.2 回调函数实现
成功回调:
void CallBackSuccess(napi_env env, napi_ref successFuncRef, int32_t count, napi_value obj)
{
napi_value results = nullptr;
napi_value successFunc = nullptr;
napi_value global = nullptr;
napi_get_global(env, &global);
napi_get_reference_value(env, successFuncRef, &successFunc);
if (successFunc == nullptr) {
return;
}
napi_call_function(env, global, successFunc, count, &obj, &results);
}
错误回调:
void CallBackError(napi_env env, napi_ref failFuncRef, string errorProp, int errorCode)
{
napi_value argvFail[2] = { 0 };
napi_value results = nullptr;
napi_value failFunc = nullptr;
napi_value global = nullptr;
napi_get_global(env, &global);
argvFail[0] = NVal::CreateUTF8String(env, errorProp).val_;
argvFail[1] = NVal::CreateInt32(env, errorCode).val_;
napi_get_reference_value(env, failFuncRef, &failFunc);
if (failFunc == nullptr) {
return;
}
napi_call_function(env, global, failFunc, COMMON_NUM::TWO, argvFail, &results);
}
技术特点
1. 异步非阻塞设计
- 所有文件操作都在后台线程执行,不会阻塞JavaScript主线程
- 使用NAPI的异步工作队列机制,确保操作的并发性和响应性
2. 统一的回调机制
- 支持success、fail、complete三种回调类型
- 提供统一的错误处理和结果返回机制
3. 路径安全验证
- 实现了完整的URI验证机制
- 防止路径遍历攻击和非法路径访问
4. 递归操作支持
- 目录操作支持递归模式
- 可以一次性创建或删除整个目录树
5. 跨平台兼容性
- 基于标准POSIX文件系统API
- 支持不同产品形态(如可穿戴设备)的特殊处理
6. 文件操作类型支持
- 文件操作:支持普通文件的创建、删除、复制、移动、读写
- 目录操作:支持目录的创建、删除、复制、移动、遍历
- 权限检查:提供文件访问权限验证机制
- 递归操作:支持目录的递归创建和删除
7. 数据读写机制
- 文本读写:支持UTF-8编码的文本文件操作
- 二进制读写:支持ArrayBuffer格式的二进制数据处理
- 位置控制:支持指定位置的文件读写操作
- 追加模式:支持文件内容的追加写入
8. 内存安全设计
- FDGuard机制:使用RAII模式自动管理文件描述符
- 智能指针:使用unique_ptr管理动态内存分配
- 异常安全:确保资源在异常情况下正确释放
使用示例
1. 创建目录
import file from '@ohos.file.file';
// 创建单个目录
file.mkdir({
uri: "internal://app/test_dir",
success: () => {
console.log("目录创建成功");
},
fail: (err) => {
console.error("目录创建失败:", err);
},
complete: () => {
console.log("操作完成");
}
});
// 递归创建目录
file.mkdir({
uri: "internal://app/parent/child/grandchild",
recursive: true,
success: () => {
console.log("递归目录创建成功");
}
});
2. 文件读写操作
// 写入文本文件
file.writeText({
uri: "internal://app/test.txt",
text: "Hello, HarmonyOS!",
append: false,
success: () => {
console.log("文本写入成功");
}
});
// 读取文本文件
file.readText({
uri: "internal://app/test.txt",
success: (data) => {
console.log("文件内容:", data);
}
});
// 写入二进制数据
const buffer = new ArrayBuffer(1024);
const view = new Uint8Array(buffer);
// ... 填充数据
file.writeArrayBuffer({
uri: "internal://app/data.bin",
buffer: buffer,
position: 0,
append: false,
success: () => {
console.log("二进制数据写入成功");
}
});
3. 文件管理操作
// 复制文件
file.copy({
srcUri: "internal://app/source.txt",
dstUri: "internal://app/destination.txt",
success: () => {
console.log("文件复制成功");
}
});
// 移动文件
file.move({
srcUri: "internal://app/old_location.txt",
dstUri: "internal://app/new_location.txt",
success: () => {
console.log("文件移动成功");
}
});
// 删除文件
file.delete({
uri: "internal://app/temp_file.txt",
success: () => {
console.log("文件删除成功");
},
fail: (err) => {
console.error("文件删除失败:", err);
}
});
// 删除目录(递归)
file.rmdir({
uri: "internal://app/old_directory",
recursive: true,
success: () => {
console.log("目录删除成功");
}
});
// 检查文件访问权限
file.access({
uri: "internal://app/important_file.txt",
success: () => {
console.log("文件可访问");
},
fail: (err) => {
console.error("文件不可访问:", err);
}
});
// 获取文件信息
file.get({
uri: "internal://app/document.pdf",
success: (fileInfo) => {
console.log("文件信息:", fileInfo);
console.log(`文件名: ${fileInfo.uri}`);
console.log(`文件大小: ${fileInfo.length} 字节`);
console.log(`文件类型: ${fileInfo.type}`);
console.log(`最后修改时间: ${fileInfo.lastModifiedTime}`);
}
});
// 列出目录内容
file.list({
uri: "internal://app/documents",
success: (fileList) => {
console.log("目录内容:", fileList);
fileList.forEach(file => {
console.log(`文件: ${file.uri}, 类型: ${file.type}, 大小: ${file.length}`);
});
}
});
4. 高级文件操作示例
// 大文件分块读取
function readLargeFile(uri, chunkSize = 1024 * 1024) {
let position = 0;
let allData = new Uint8Array(0);
function readChunk() {
file.readArrayBuffer({
uri: uri,
length: chunkSize,
position: position,
success: (data) => {
const newData = new Uint8Array(data);
const combined = new Uint8Array(allData.length + newData.length);
combined.set(allData);
combined.set(newData, allData.length);
allData = combined;
position += newData.length;
if (newData.length === chunkSize) {
readChunk(); // 继续读取下一块
} else {
console.log("文件读取完成,总大小:", allData.length);
// 处理完整数据
}
},
fail: (err) => {
console.error("读取失败:", err);
}
});
}
readChunk();
}
// 文件备份功能
function backupFile(srcUri, backupUri) {
file.copy({
srcUri: srcUri,
dstUri: backupUri,
success: () => {
console.log("文件备份成功");
},
fail: (err) => {
console.error("文件备份失败:", err);
}
});
}
// 批量文件操作
function batchFileOperations() {
const files = [
"internal://app/file1.txt",
"internal://app/file2.txt",
"internal://app/file3.txt"
];
let completed = 0;
const total = files.length;
files.forEach(fileUri => {
file.delete({
uri: fileUri,
success: () => {
completed++;
console.log(`删除文件 ${fileUri} 成功 (${completed}/${total})`);
if (completed === total) {
console.log("所有文件删除完成");
}
},
fail: (err) => {
console.error(`删除文件 ${fileUri} 失败:`, err);
}
});
});
}
性能优化
1. 内存管理
- 使用智能指针管理内存,避免内存泄漏
- 及时释放NAPI引用和异步工作句柄
2. 错误处理优化
- 统一的错误码定义,便于问题定位
- 详细的错误信息返回,提升调试体验
3. 并发控制
- 异步操作避免阻塞主线程
- 支持多个文件操作并发执行
总结
mod_file模块作为OpenHarmony文件系统的核心接口,提供了完整、安全、高效的文件操作能力。该模块共实现了12个核心API接口,涵盖了文件/目录的创建、删除、复制、移动、读写、权限检查等全部基础功能。
核心特性总结
全面的文件操作支持:
- 12个核心API接口,覆盖所有基础文件操作需求
- 支持文件和目录的完整生命周期管理
- 提供文本和二进制数据的读写能力
异步非阻塞架构:
- 所有操作采用异步模式,避免阻塞JavaScript主线程
- 基于NAPI异步工作队列,确保高并发性能
- 统一的回调机制,支持success、fail、complete三种回调类型
安全可靠的实现:
- 完整的URI验证机制,防止路径遍历攻击
- 内存安全设计,使用RAII和智能指针管理资源
- 详细的错误处理和错误码定义
高性能优化:
- 使用sendfile系统调用优化文件复制性能
- 支持大文件分块读写,避免内存溢出
- 递归操作支持,提高批量操作效率
跨平台兼容性:
- 基于标准POSIX文件系统API
- 支持不同产品形态的特殊处理
- 统一的接口设计,屏蔽底层差异