1、需求简介
有这样一个需求:lazarus应用程序需要对 data 和 sys 文件夹中的子文件夹及文件进行读写、创建。这在windows平台和linux平台都很容易实现。现在需要在鸿蒙平台实现这些功能。
把2个文件夹放在鸿蒙项目文件夹:
entry\src\main\resources\rawfile
由于lazarus应用对rawfile文件夹没有读写权限,改为将2个文件夹放在
entry\src\main\resources\resfile
hap安装后,resfile 资源会被解压到应用沙箱路径中。
现在需要验证 resfile 下的 data 文件夹是否已正确打包并部署到模拟器,可以通过 hdc 命令在 DevEco Studio 终端中查看
2、 命令行方式查看应用沙箱下 el2/base 目录的文件列表
(包名: com.example.hello20260714b)
perl
hdc shell -b com.example.hello20260714b ls -A "./data/storage/el2/base/"
-b {bundleName} 参数表示以指定应用的身份执行命令,这样可以正确访问应用沙箱目录。
运行结果:
.backup
cache
files
haps
preferences
3、查看 haps 目录
perl
hdc shell -b com.example.hello20260714b ls -A "./data/storage/el2/base/haps/"
运行结果:
entry
4、在 click 事件中获取并显示resfile对应的路径代码
修改 index.ets 代码,在日志信息中查看resfile对应的资源路径(resourceDir)
修改 Index.ets,在 click 事件中添加获取并显示路径代码。
TypeScript
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
this.message = 'Welcome';
// 获取 resourceDir 路径并打印
let context = getContext(this) as common.UIAbilityContext;
console.info(`resourceDir 路径: ${context.resourceDir}`);
})
}
.height('100%')
.width('100%')
}
}
点击 hello world,hilog中显示:
07-15 14:09:32.299 3855-3855 A03d00/JSAPP com.examp...0260714b I resourceDir 路径: /data/storage/el1/bundle/entry/resources/resfile
此时仍然不能确认 data 、sys 文件夹是否被正确放在沙箱的 resfile 文件夹中。
5、查看虚拟机中资源路径( resourceDir)包含的内容
修改 index.ets 代码
TypeScript
import { common } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
const DOMAIN: number = 0x0010;
// tag: 日志标签,用于标识日志的来源,便于在日志窗口中筛选
const TAG: string = 'search_dir';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
@State fileList: string[] = [];
aboutToAppear(): void {
// 获取context(假设在AbilityStage或UIAbility中)
let context = getContext(this) as common.UIAbilityContext;
// resfile资源目录(只读,应用安装后自动解压到此)
const resDir = context.resourceDir;
// resourceDir 只读路径 -----------------------------------------------
hilog.info(DOMAIN, TAG, `只读的 resourceDir 路径: ${resDir}`);
try {
// 列出 resourceDir 目录下的所有文件和文件夹
let list = fileIo.listFileSync(context.resourceDir);
hilog.info(DOMAIN, TAG, `只读的 resourceDir 根目录内容: ${JSON.stringify(list)}`);
// 尝试列出 data 子目录
let dataPath = `${resDir}/data`;
let dataList = fileIo.listFileSync(dataPath);
hilog.info(DOMAIN, TAG, `只读的 resourceDir/data 目录内容: ${JSON.stringify(dataList)}`);
// 尝试列出 sys 子目录
let sysPath = `${resDir}/sys`;
let sysList = fileIo.listFileSync(sysPath);
hilog.info(DOMAIN, TAG, `只读的 resourceDir/sys 目录内容: ${JSON.stringify(sysList)}`);
} catch (e) {
hilog.info(DOMAIN, TAG, `列出目录失败: ${(e as Error).message}`);
}
// resourceDir 只读路径 ===============================================
// 沙箱可读写目录 ----------------------------------
const sandboxDir = context.filesDir;
const srcPath = `${resDir}/data`;
const destPath = `${sandboxDir}/data`;
try {
hilog.info(DOMAIN, TAG, `可读写的沙箱路径 sandboxDir: ${sandboxDir}`);
// 先检查目标目录是否存在,不存在则创建
if (!fs.accessSync(destPath)) {
fs.mkdirSync(destPath);
}
// 将 resfile 中的 data 目录复制到沙箱可读写目录
fs.copyDirSync(srcPath, destPath);
hilog.info(DOMAIN, TAG, `复制成功,可在沙箱目录中读写data文件夹: ${destPath}`);
} catch (error) {
let err2 = error as BusinessError;
hilog.info(DOMAIN, TAG, `复制失败: Code: ${err2.code}, message: ${err2.message}`);
}
// 沙箱可读写目录 ================================================
}
build() {
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
this.message = 'Welcome';
// 获取 resourceDir 路径并打印
let context = getContext(this) as common.UIAbilityContext;
console.info(`resourceDir 路径: ${context.resourceDir}`);
})
}
.height('100%')
.width('100%')
}
}
运行后,HiLog 过滤 resourceDir 关键词显示内容:
只读的 resourceDir 路径: /data/storage/el1/bundle/entry/resources/resfile
只读的 resourceDir 根目录内容: "sys","data"
只读的 resourceDir/data 目录内容: "370000000000000000","370000000000000002"
只读的 resourceDir/sys 目录内容: "tpl","reg_help.mht","setup.ini",
可读写的沙箱路径 sandboxDir: /data/storage/el2/base/haps/entry/files
复制失败: Code: 13900015, message: File exists
说明2个定制文件夹打包并安装成功了。
备注:resfile 目录中的资源只能以只读方式访问1,如果需要读写操作,需要先将文件复制到应用的 filesDir 沙箱目录中