HarmonyOS 鸿蒙Next中fileIo.mkdirSync方法报错:fileIo.mkdirSync
HarmonyOS 鸿蒙Next中fileIo.mkdirSync方法报错:fileIo.mkdirSync
fileIo.mkdirSync('/data/account', true)
这行递归创建文件目录的代码报错:Permission denied,请问是需要什么权限嘛,API文档里也没写要申请权限啊,求教
可以参考这个沙箱文件使用
【背景知识】
-
- 什么是应用沙箱目录?
- 对于每个应用,系统会在内部存储空间映射出一个专属的“沙箱目录”,应用可见的目录范围即为“应用沙箱目录”。
- 应用沙箱目录组成?
- 应用沙箱目录是“应用文件目录”与一部分系统文件(应用运行必需的少量系统文件)所在的目录组成的集合。
- 应用沙箱作用
- 应用沙箱限制了应用可见的数据范围。在“应用沙箱目录”中,应用仅能看到自己的应用文件以及少量的系统文件(应用运行必需的少量系统文件)。因此,本应用的文件也不为其他应用可见,从而保护了应用文件的安全。
- 应用可以在“应用文件目录”下保存和处理自己的应用文件;系统文件及其目录对于应用是只读的;而应用若需访问用户文件,则需要通过特定API同时经过用户的相应授权才能进行。
- 什么是应用沙箱目录?
-
- 关系型数据库Relational Database,RDB是一种基于关系模型来管理数据的数据库。关系型数据库基于SQLite组件提供了一套完整的对本地数据库进行管理的机制,对外提供了一系列的增、删、改、查等接口,也可以直接运行用户输入的SQL语句来满足复杂的场景需要。
- ArkTS提供了
@ohos.data.relationalStore
包,支持SQLite组件的增、删、改、查,以及通过ResultSet.getSendableRow
方法获取Sendable数据,进行跨线程传递等众多通用数据库操作接口。
【解决方案】
基于安全访问要求,目前不支持直接在rawfile目录下去进行读写数据库,数据库文件必须放在数据库相关的沙箱路径及其子目录下,应用才能访问。
如上述情形:将db文件下载到了rawfile目录中,可以考虑将db文件拷贝至数据库存储沙箱路径,再借助@ohos.data.relationalStore
包进行数据库处理;
数据库查询参见:【数据库查询访问API参考】;代码处理步骤:
- 借助
getContext(this).getApplicationContext().databaseDir
创建好应用沙箱数据库目录; - 使用
getContext(this).resourceManager.getRawFd
获取rawfile目录里面的原始数据库文件信息; - 调用
saveFileToSandbox
将【2】中获取的原始数据库文件写入【1】中已创建好的沙箱数据库目录;
参考如下代码:
import fs, { ReadOptions } from '@ohos.file.fs';
import { resourceManager } from '@kit.LocalizationKit';
@Entry
@Component
struct Index {
aboutToAppear(): void {
this.initDataBaseDir();
}
build() {
RelativeContainer() {
Text('test')
.id('HelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
}
.height('100%')
.width('100%')
}
saveFileToSandbox(file: resourceManager.RawFileDescriptor, dbName: string) {
// 创建缓存文件(当前是覆盖式创建)
let cFile = getContext(this).getApplicationContext().databaseDir + "/entry/rdb/" + dbName
let cacheFile = fs.openSync(cFile, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
// 读取缓冲区大小
let bufferSize = 30000
let buffer = new ArrayBuffer(bufferSize); // 创建buffer缓冲区
// 要copy的文件的offset和length
let currentOffset = file.offset;
let readOption: ReadOptions = {
offset: currentOffset, // 期望读取文件的位置。可选,默认从当前位置开始读
length: bufferSize // 每次期望读取数据的长度。可选,默认缓冲区长度
}
// 后面len会一直减,直到没有
while (true) {
// 读取buffer容量的内容
let readLength = fs.readSync(file.fd, buffer, readOption);
// 写入buffer容量的内容
// 写到cacheFile里
fs.writeSync(cacheFile.fd, buffer, { length: readLength })
// 判断后续内容,修改读文件的参数
// buffer没读满代表文件读完了
if (readLength < bufferSize) {
break;
}
if (readOption.offset != undefined) {
readOption.offset += readLength;
}
}
console.log("Copy Success!!!")
fs.close(cacheFile);
}
initDataBaseDir() {
// 创建数据库沙箱目录
try {
let dirPath = getContext(this).getApplicationContext().databaseDir + "/entry"
fs.mkdirSync(dirPath);
dirPath = dirPath + "/rdb"
fs.mkdirSync(dirPath);
} catch (error) {
console.error('initDataBaseDir err');
}
// 数据库名称
let dbName: string = 'Company.db'
// 读取rawfile目录下db文件
try {
getContext(this).resourceManager.getRawFd('rdb/' + dbName, (error, value) => {
if (error != null) {
console.error('callback getRawFd failed error');
} else {
console.info(value.length.toString())
this.saveFileToSandbox(value, dbName)
}
});
} catch (error) {
console.error('callback getRawFd failed')
}
}
}
更多关于HarmonyOS 鸿蒙Next中fileIo.mkdirSync方法报错:fileIo.mkdirSync的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
看下沙箱文件目录,我们应该使用四级以后的目录,来做文件处理。之前的目录很可能是禁止写入的。
也不推荐直接拼接路径,比如 data/storage/xxx
,
而是通过上下文去获取沙箱目录,比如:
this.context.filesDir
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/app-sandbox-directory
懂了,谢啦,
在HarmonyOS鸿蒙Next中,fileIo.mkdirSync报错通常由以下原因导致:
- 路径无效或格式错误(需使用应用沙箱路径如
this.filesDir + "/newDir"
) - 目录已存在(需先调用fileIo.accessSync检查)
- 权限不足(需在config.json中声明ohos.permission.FILE_ACCESS权限)
- 父目录不存在(需确保上级目录存在)
典型错误代码:BusinessError: 13900004
表示文件已存在,13900002
表示无权限。