HarmonyOS 鸿蒙Next中sqlite的DB文件的拷贝
HarmonyOS 鸿蒙Next中sqlite的DB文件的拷贝 如何将已有sqlite的db文件拷贝到沙箱里(鸿蒙app默认文件路径)。
能否提供一个完整例子。
开发环境:HarmonyOS 6.0.0 Release SDK,原样包含OpenHarmony SDK Ohos_sdk_public 6.0.0.47 (API Version 20 Release)
开发者你好,参考文档将rawfile文件夹下的db文件推到数据存储沙箱路径:
【解决方案】
-
将db文件推送到数据存储沙箱路径:/data/app/el2/100/database/(bundleName)/entry/rdb/。实现方式为使用文件管理接口打开本地数据库,读取其内容并写入沙箱路径下的db文件中。
import { fileIo } from '@kit.CoreFileKit'; import { relationalStore } from '@kit.ArkData'; import { common } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; // Obtaining the Context in EntryAbility, save it to AppStorage, then use AppStorage to retrieve it in the utility class. let context = AppStorage.get('context') as UIContext; let UiAbilityContent = context.getHostContext() as common.UIAbilityContext; let RDBDirectory = UiAbilityContent.databaseDir; let resource = UiAbilityContent.resourceManager; function initDatabase() { // Create a database sandbox directory try { let dirPath = RDBDirectory + '/entry'; fileIo.mkdirSync(dirPath); dirPath = dirPath + '/rdb'; fileIo.mkdirSync(dirPath); } catch (error) { console.error(`mkdir rdbPath failed, error code: ${error.code}, message: ${error.message}.`); } // Set db name let dbName: string = 'Objective.db'; // Read the db file in the rawfile directory try { let content = resource.getRawFileContentSync(dbName); let cFile = RDBDirectory + '/entry/rdb/' + dbName; let cacheFile = fileIo.openSync(cFile, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); fileIo.write(cacheFile.fd, content.buffer); fileIo.closeSync(cacheFile.fd); } catch (error) { console.error(`callback getRawFd failed, error code: ${error.code}, message: ${error.message}.`); } } -
通过getRdbStore获取保存在沙箱路径下的db文件
async function getRDB(): Promise<relationalStore.RdbStore | undefined> { let result: relationalStore.RdbStore | undefined = undefined; const STORE_CONFIG: relationalStore.StoreConfig = { name: 'Objective.db', securityLevel: relationalStore.SecurityLevel.S1 }; await relationalStore.getRdbStore(UiAbilityContent, STORE_CONFIG).then((rdbStore: relationalStore.RdbStore) => { result = rdbStore; console.info('Get RdbStore successfully.'); }).catch((err: BusinessError) => { console.error(`Get RdbStore failed, code is ${err.code}, message is ${err.message}`); }); return result; }
更多关于HarmonyOS 鸿蒙Next中sqlite的DB文件的拷贝的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在鸿蒙(HarmonyOS)开发中,将预置的 SQLite 数据库文件(.db)拷贝到应用1沙箱路径的操作需要遵循特定的安全规范。以下是完整解决方案和代码示例,适用于 HarmonyOS 6.0.0 (API Version 20):
核心步骤说明
-
沙箱路径规定 数据库文件必须放在应用沙箱路径:
/data/app/el2/100/database/<bundleName>/entry/rdb/或其子目录下(234) -
最佳实践 将预置的 .db 文件放在
resources/rawfile目录,通过文件操作 API 移动到沙箱路径
完整代码实现
// 文件操作模块
import fs from '@kit.ArkFileIO';
// 关系型数据库模块
import relationalStore from '@kit.ArkData';
async function copyDbToSandbox(context: common.Context) {
try {
// 1. 定义路径
const srcPath = 'resource://rawfile/your_db.db'; // rawfile中的源文件
const destDir = context.databaseDir + '/rdb/'; // 沙箱数据库目录
const destPath = destDir + 'your_db.db';
// 2. 创建目标目录
await fs.ensureDir(destDir);
// 3. 复制文件
const srcFile = await fs.open(srcPath, fs.OpenMode.READ_ONLY);
const destFile = await fs.open(destPath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
const stat = await fs.stat(srcPath);
const buffer = new ArrayBuffer(stat.size);
await fs.read(srcFile.fd, buffer);
await fs.write(destFile.fd, buffer);
await fs.close(srcFile.fd);
await fs.close(destFile.fd);
console.log('Database copied to sandbox');
// 4. 初始化数据库连接
const storeConfig: relationalStore.StoreConfig = {
name: destPath,
encrypt: false // 若需加密设为true并配置密钥
};
relationalStore.getRdbStore(context, storeConfig, (err, store) => {
if (err) {
console.error(`Database init failed: ${err.message}`);
} else {
console.log('Database connection opened');
// 执行数据库操作...
}
});
} catch (error) {
console.error(`File operation error: ${error.message}`);
}
}
关键注意事项
-
路径权限
- 只能访问
context.databaseDir指定的沙箱路径(4) - 直接访问设备其他目录会被系统拒绝
- 只能访问
-
加密配置 若需加密数据库,在
StoreConfig中设置:encrypt: true, securityLevel: relationalStore.SecurityLevel.S1 // 安全级别 -
文件完整性
- 避免直接操作 .db 文件,应使用
backup()/restore()API() - 复制后可通过
fs.hash()验证文件完整性
- 避免直接操作 .db 文件,应使用
调用示例
在 Ability 的 onCreate方法中调用:
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate() {
copyDbToSandbox(this.context).catch(console.error);
}
}
重要提示:
- 实际路径中的
<bundleName>会自动替换为应用包名- 若使用加密数据库,需保证加密/解密参数完全一致(23)
- 此方案适用于 API Version 20+,兼容 HarmonyOS 6.0.0 SDK
信息来源
下面代码演示了将 resoutces/rawfile/ 目录下的db文件 拷贝到沙箱文件目录,db文件命名相同.
// 将 resoutces/rawfile/mysqlite.db 拷贝到沙箱目录
private async copyDBToSandboxPath() {
try {
const context = this.getUIContext().getHostContext()
const path = context?.filesDir + '/mysqlite.db'
const buf = await context?.resourceManager.getRawFileContent('mysqlite.db')
const outFile =
await fileIo.open(path, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC)
await fileIo.write(outFile.fd, buf?.buffer)
await fileIo.close(outFile.fd)
} catch (e) {
}
}
使用Docker部署MySQL
1. 拉取MySQL镜像
docker pull mysql:8.0
2. 创建数据卷
docker volume create mysql_data
docker volume create mysql_conf
3. 创建自定义配置文件
在宿主机上创建配置文件目录并添加 my.cnf 文件:
mkdir -p /docker/mysql/conf
编辑 /docker/mysql/conf/my.cnf:
[mysqld]
user=mysql
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default_authentication_plugin=mysql_native_password
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
4. 运行MySQL容器
docker run -d \
--name mysql \
--restart always \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=your_password \
-v mysql_data:/var/lib/mysql \
-v /docker/mysql/conf:/etc/mysql/conf.d \
mysql:8.0
参数说明:
-d:后台运行--name:容器名称--restart always:自动重启-p:端口映射(宿主机端口:容器端口)-e:环境变量(设置root密码)-v:挂载数据卷和配置文件
5. 常用Docker命令
# 查看容器状态
docker ps -a
# 查看容器日志
docker logs mysql
# 进入容器
docker exec -it mysql bash
# 停止容器
docker stop mysql
# 启动容器
docker start mysql
# 删除容器
docker rm mysql
6. 连接MySQL
# 进入容器连接
docker exec -it mysql mysql -uroot -p
# 或从外部连接
mysql -h 127.0.0.1 -P 3306 -uroot -p
注意事项
- 将
your_password替换为实际的强密码 - 生产环境建议使用更复杂的密码策略
- 数据卷确保数据持久化
- 配置文件可根据实际需求调整
鸿蒙Next中SQLite数据库文件拷贝可通过FileManager API实现。使用ohos.file.fs模块的copyFile方法直接复制源文件到目标路径。需注意应用沙箱权限,源文件需位于应用可访问目录,目标路径需有写入权限。操作前应关闭数据库连接,避免文件锁定导致复制失败。
在HarmonyOS Next中,将预置的SQLite数据库文件从应用安装包(resources/rawfile目录)拷贝到应用沙箱路径,是实现数据初始化的常见需求。以下是一个基于API Version 20的完整示例,展示了如何安全、高效地完成此操作。
核心步骤与代码示例
-
放置数据库文件:将你的预置数据库文件(例如
preload.db)放入项目的resources/rawfile目录下。 -
实现拷贝逻辑:在应用启动时(例如在
EntryAbility的onWindowStageCreate中)或需要时调用以下方法。
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
async function copyPreloadedDatabase(context: common.UIAbilityContext): Promise<void> {
// 1. 定义目标沙箱路径
const sandboxDir: string = context.filesDir;
const targetDbPath: string = sandboxDir + '/myapp.db'; // 你的目标数据库文件名
// 2. 检查目标文件是否已存在,避免重复拷贝
try {
await fs.access(targetDbPath);
console.info('Database already exists at target path.');
return;
} catch (error) {
// 文件不存在,继续执行拷贝
console.info('Target database does not exist, proceeding with copy.');
}
// 3. 从rawfile读取源文件
const sourceDbFile: fs.File = await context.resourceManager.getRawFile('preload.db');
const stat: fs.Stat = await fs.stat(sourceDbFile.fd);
const fileSize: number = stat.size;
// 4. 创建读取流(源文件)和写入流(目标文件)
const readStream: fs.Stream = fs.createStreamSync(sourceDbFile.fd, 'r');
const writeStream: fs.Stream = fs.createStreamSync(targetDbPath, 'w');
// 5. 使用流式拷贝,适合大文件,避免内存压力
const bufferSize: number = 4096; // 4KB缓冲区
let totalBytesRead: number = 0;
while (totalBytesRead < fileSize) {
const readSize: number = Math.min(bufferSize, fileSize - totalBytesRead);
const buffer: ArrayBuffer = new ArrayBuffer(readSize);
const bytesRead: number = await readStream.read(buffer);
if (bytesRead > 0) {
await writeStream.write(buffer);
totalBytesRead += bytesRead;
} else {
break;
}
}
// 6. 关闭流并同步文件确保数据写入磁盘
readStream.closeSync();
writeStream.closeSync();
await fs.fsync(writeStream.fd);
console.info('Database copied successfully to: ' + targetDbPath);
}
// 在Ability中调用示例
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// ... 其他初始化代码
copyPreloadedDatabase(this.context).then(() => {
console.info('Database copy process completed.');
// 此处可以初始化你的数据库连接
}).catch((err: Error) => {
console.error('Failed to copy database: ' + JSON.stringify(err));
});
}
}
关键点说明
- 目标路径:
context.filesDir指向应用沙箱的文件目录,数据在此处可读写且对其他应用私有。 - 流式操作:使用
fs.createStreamSync创建读写流进行分块拷贝,这对于较大的数据库文件至关重要,可以避免一次性加载整个文件到内存中。 - 存在性检查:拷贝前使用
fs.access检查目标文件是否存在,防止每次启动都重复覆盖。 - 数据完整性:拷贝完成后调用
fs.fsync确保所有数据从系统缓冲区刷新到物理存储。 - 错误处理:示例中包含基本的错误处理,在实际开发中应根据需要进一步细化。
后续使用
拷贝完成后,你可以使用 @ohos.data.relationalStore 或 @ohos.data.rdb 等HarmonyOS数据管理API,通过目标路径 targetDbPath 来打开并操作这个数据库。
此方法直接、高效,是HarmonyOS Next中处理预置数据库文件的推荐方式。

