开源 Arkts 鸿蒙应用 开发(六)数据持久--文件和首选项存储
文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。
相关链接:
开源 Arkts 鸿蒙应用 开发(一)工程文件分析-CSDN博客
开源 Arkts 鸿蒙应用 开发(二)封装库.har制作和应用-CSDN博客
开源 Arkts 鸿蒙应用 开发(三)Arkts的介绍-CSDN博客
开源 Arkts 鸿蒙应用 开发(四)布局和常用控件-CSDN博客
开源 Arkts 鸿蒙应用 开发(五)控件组成和复杂控件-CSDN博客
开源 Arkts 鸿蒙应用 开发(六)数据持久--文件和首选项存储-CSDN博客
开源 Arkts 鸿蒙应用 开发(七)数据持久--sqlite关系数据库-CSDN博客
开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机-CSDN博客
开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端-CSDN博客
开源 Arkts 鸿蒙应用 开发(十)通讯--Http数据传输-CSDN博客
推荐链接:
开源 java android app 开发(一)开发环境的搭建-CSDN博客
开源 java android app 开发(二)工程文件结构-CSDN博客
开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客
开源 java android app 开发(四)GUI界面重要组件-CSDN博客
开源 java android app 开发(五)文件和数据库存储-CSDN博客
开源 java android app 开发(六)多媒体使用-CSDN博客
开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客
开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客
开源 java android app 开发(九)后台之线程和服务-CSDN博客
开源 java android app 开发(十)广播机制-CSDN博客
开源 java android app 开发(十一)调试、发布-CSDN博客
开源 java android app 开发(十二)封库.aar-CSDN博客
推荐链接:
开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客
开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客
开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客
开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客
开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客
本章节内容如下:
1. 文件存储
2. 首选项存储
一、文件读写,实现了按键将对话框数据对写入文件,按键读取文件数据到对话框。写入后,关闭app,重新打开后再读出,验证文件存取成功。
1.1 写入文件和读出文件代码
writeToFile() { try { let file = fs.openSync(this.filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); fs.writeSync(file.fd, this.inputText); fs.closeSync(file.fd); this.outputText = \'内容已成功写入文件\'; console.log(\'写入文件成功\'); } catch (error) { console.error(`写入文件失败: ${error.message}`); this.outputText = \'写入文件失败\'; } } readFromFile() { try { if (!fs.accessSync(this.filePath)) { this.outputText = \'文件不存在\'; return; } let file = fs.openSync(this.filePath, fs.OpenMode.READ_ONLY); let stat = fs.statSync(this.filePath); let arrayBuffer = new ArrayBuffer(stat.size); fs.readSync(file.fd, arrayBuffer); fs.closeSync(file.fd); // 使用循环将Uint8Array转换为字符串 const uint8Array = new Uint8Array(arrayBuffer); let result = \'\'; for (let i = 0; i < uint8Array.length; i++) { result += String.fromCharCode(uint8Array[i]); } this.outputText = result; } catch (error) { console.error(`读取文件失败: ${error.message}`); this.outputText = \'读取文件失败\'; } }
1.2 界面代码
build() { Column({ space: 20 }) { TextInput({ placeholder: \'请输入要保存的内容\' }) .width(\'90%\') .height(60) .onChange((value: string) => { this.inputText = value; }) Button(\'写入文件\') .width(\'60%\') .height(40) .onClick(() => { this.writeToFile(); }) TextInput({ placeholder: \'文件内容将显示在这里\', text: this.outputText }) .width(\'90%\') .height(60) Button(\'读取文件\') .width(\'60%\') .height(40) .onClick(() => { this.readFromFile(); }) } .width(\'100%\') .height(\'100%\') .justifyContent(FlexAlign.Center) }
1.3 \\pages\\index.ets代码
// MainAbility.etsimport common from \'@ohos.app.ability.common\';import fs from \'@ohos.file.fs\';@Entry@Componentstruct FileReadWriteExample { @State inputText: string = \'\'; @State outputText: string = \'\'; private context = getContext(this) as common.UIAbilityContext; private filePath: string = \'\'; aboutToAppear() { this.filePath = this.context.filesDir + \'/example.txt\'; console.log(`文件路径: ${this.filePath}`); } writeToFile() { try { let file = fs.openSync(this.filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); fs.writeSync(file.fd, this.inputText); fs.closeSync(file.fd); this.outputText = \'内容已成功写入文件\'; console.log(\'写入文件成功\'); } catch (error) { console.error(`写入文件失败: ${error.message}`); this.outputText = \'写入文件失败\'; } } readFromFile() { try { if (!fs.accessSync(this.filePath)) { this.outputText = \'文件不存在\'; return; } let file = fs.openSync(this.filePath, fs.OpenMode.READ_ONLY); let stat = fs.statSync(this.filePath); let arrayBuffer = new ArrayBuffer(stat.size); fs.readSync(file.fd, arrayBuffer); fs.closeSync(file.fd); // 使用循环将Uint8Array转换为字符串 const uint8Array = new Uint8Array(arrayBuffer); let result = \'\'; for (let i = 0; i { this.inputText = value; }) Button(\'写入文件\') .width(\'60%\') .height(40) .onClick(() => { this.writeToFile(); }) TextInput({ placeholder: \'文件内容将显示在这里\', text: this.outputText }) .width(\'90%\') .height(60) Button(\'读取文件\') .width(\'60%\') .height(40) .onClick(() => { this.readFromFile(); }) } .width(\'100%\') .height(\'100%\') .justifyContent(FlexAlign.Center) }}
1.4 演示
二、首选项读写
2.1 页面显示代码index.ets,实现显示3个按钮。
// index.ets@Entry@Componentstruct Index { build() { Column() { Button(\'Button 1\') .margin({ top: 10, bottom: 10 }) .onClick(() => { // 通过全局对象调用Ability方法 if (globalThis.entryAbility?.btn1) { globalThis.entryAbility.btn1(); } }) .width(\'100%\') Row() Button(\'Button 2\') .margin({ top: 10, bottom: 10 }) .onClick(() => { if (globalThis.entryAbility?.btn2) { globalThis.entryAbility.btn2(); } }) .width(\'100%\') Button(\'Button 3\') .margin({ top: 10, bottom: 10 }) .onClick(() => { if (globalThis.entryAbility?.btn3) { globalThis.entryAbility.btn3(); } }) .width(\'100%\') } .width(\'100%\') .height(\'100%\') }}
2.2 UIAbility的代码EntryAbility.ets,功能包括
初始化Preferences数据存储
提供三个按钮操作:
btn1(): 写入字符串、二进制数据和数字到Preferences
btn2(): 从Preferences读取并显示存储的数据
btn3(): 删除Preferences中的数据
Preferences操作
代码中提供了完整的Preferences CRUD操作:
初始化:initPreferences()异步方法
写入数据:btn1()使用putSync()同步写入三种类型数据、字符串、二进制数据(Uint8Array)、数字
读取数据:btn2()使用getSync()同步读取数据、使用TextDecoder解码二进制数据
删除数据:btn3()使用deleteSync()同步删除数据
Preferences同步/异步操作:
初始化使用异步getPreferences()
数据操作使用同步方法(putSync, getSync, deleteSync)
写入后调用flushSync()确保数据持久化
以下为代码
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from \'@kit.AbilityKit\';import { hilog } from \'@kit.PerformanceAnalysisKit\';import { window } from \'@kit.ArkUI\';import { BusinessError } from \'@kit.BasicServicesKit\';import { preferences } from \'@kit.ArkData\';import { util } from \'@kit.ArkTS\';const DOMAIN = 0x0000;let dataPreferences: preferences.Preferences | null = null;export default class EntryAbility extends UIAbility { // 初始化Preferences async initPreferences(): Promise { try { let options: preferences.Options = { name: \'myStore\' }; dataPreferences = await preferences.getPreferences(this.context, options); } catch (err) { hilog.error(DOMAIN, \'testTag\', \'Failed to get preferences. Cause: %{public}s\', JSON.stringify(err)); } } // 按钮1:写入数据 btn1(): void { if (!dataPreferences) { console.error(\'click btn1 Preferences not initialized\'); return; } try { // 写入字符串 dataPreferences.putSync(\'string_key\', \'Hello ArkTS\'); // 写入Uint8Array let encoder = new util.TextEncoder(); let uInt8Array = encoder.encodeInto(\"你好,ArkTS\"); dataPreferences.putSync(\'binary_key\', uInt8Array); // 写入数字 dataPreferences.putSync(\'number_key\', 123); dataPreferences.flushSync(); console.info(\'click btn1 Preferences Data written successfully\'); } catch (err) { console.error(\'click btn1 Preferences Failed to write data: \' + JSON.stringify(err)); } } // 按钮2:读取数据 btn2(): void { if (!dataPreferences) { console.error(\'click btn2 Preferences not initialized\'); return; } try { // 读取字符串 let stringVal = dataPreferences.getSync(\'string_key\', \'default\'); console.info(\'click btn2 Preferences String value: \' + stringVal); // 读取二进制数据 let binaryVal = dataPreferences.getSync(\'binary_key\', new Uint8Array(0)); let decoder = new util.TextDecoder(\'utf-8\'); let decodedStr = decoder.decode(binaryVal as Uint8Array); console.info(\'click btn2 Preferences Binary value: \' + decodedStr); // 读取数字 let numberVal = dataPreferences.getSync(\'number_key\', 0); console.info(\'click btn2 Preferences Number value: \' + numberVal); } catch (err) { console.error(\'click btn2 Preferences Failed to read data: \' + JSON.stringify(err)); } } // 按钮3:删除数据 btn3(): void { if (!dataPreferences) { console.error(\'click btn3 Preferences not initialized\'); return; } try { dataPreferences.deleteSync(\'string_key\'); dataPreferences.deleteSync(\'binary_key\'); dataPreferences.deleteSync(\'number_key\'); console.info(\'click btn3 Preferences Data deleted successfully\'); } catch (err) { console.error(\'click btn3 Preferences Failed to delete data: \' + JSON.stringify(err)); } } onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); hilog.info(DOMAIN, \'testTag\', \'%{public}s\', \'Ability onCreate\'); globalThis.abilityContext = this.context; globalThis.entryAbility = this; // 初始化Preferences this.initPreferences(); } onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(DOMAIN, \'testTag\', \'%{public}s\', \'Ability onWindowStageCreate\'); windowStage.loadContent(\'pages/Index\', (err) => { if (err.code) { hilog.error(DOMAIN, \'testTag\', \'Failed to load the content. Cause: %{public}s\', JSON.stringify(err)); return; } hilog.info(DOMAIN, \'testTag\', \'Succeeded in loading the content.\'); }); /* let options: preferences.Options = { name: \'myStore\' }; dataPreferences = preferences.getPreferencesSync(this.context, options); if (dataPreferences.hasSync(\'startup\')) { console.info(\"The key \'startup\' is contained.\"); } else { console.info(\"The key \'startup\' does not contain.\"); // 此处以此键值对不存在时写入数据为例 dataPreferences.putSync(\'startup\', \'auto\'); // 当字符串有特殊字符时,需要将字符串转为Uint8Array类型再存储,长度均不超过16 * 1024 * 1024个字节。 //let uInt8Array1 = new util.TextEncoder().encodeInto(\"~!@#¥%……&*()——+?\"); let encoder: util.TextEncoder = new util.TextEncoder(); let uInt8Array1: Uint8Array = encoder.encodeInto(\"你好,ArkTS\"); // 或 encode() dataPreferences.putSync(\'uInt8\', uInt8Array1); } let val = dataPreferences.getSync(\'startup\', \'default\'); console.info(\"The \'startup\' value is \" + val); // 当获取的值为带有特殊字符的字符串时,需要将获取到的Uint8Array转换为字符串 let uInt8Array2 : preferences.ValueType = dataPreferences.getSync(\'uInt8\', new Uint8Array(0)); let textDecoder = util.TextDecoder.create(\'utf-8\'); val = textDecoder.decodeToString(uInt8Array2 as Uint8Array); console.info(\"The \'uInt8\' value is \" + val); */ } onWindowStageDestroy(): void { // Main window is destroyed, release UI related resources hilog.info(DOMAIN, \'testTag\', \'%{public}s\', \'Ability onWindowStageDestroy\'); } onForeground(): void { // Ability has brought to foreground hilog.info(DOMAIN, \'testTag\', \'%{public}s\', \'Ability onForeground\'); } onBackground(): void { // Ability has back to background hilog.info(DOMAIN, \'testTag\', \'%{public}s\', \'Ability onBackground\'); }}
2.3 测试效果如下,测试了写入,读出,删除。删除后再读出则为空。