当前位置: 首页 > article >正文

缓存和客户端数据存储体系(Ark Data Kit)--- 应用数据持久化(首选项持久化、K-V、关系型数据库)持续更新中...

Core File Kit做怎删改查操作不便,用Ark Data Kit。

功能介绍

ArkData (方舟数据管理)为开发者提供数据存储、数据管理和数据同步能力,比如联系人应用数据可以保存到数据库中,提供数据库的安全、可靠以及共享访问等管理机制,也支持与手表同步联系人信息。

  • 标准化数据定义:提供HarmonyOS跨应用、跨设备的统一数据类型标准,包含标准化数据类型和标准化数据结构。

  • 数据存储:提供通用数据持久化能力,根据数据特点,分为用户首选项、键值型数据库和关系型数据库。

  • 数据管理:提供高效的数据管理能力,包括权限管理、数据备份恢复、数据共享框架等。

  • 数据同步:提供跨设备数据同步能力,比如分布式对象支持内存对象跨设备共享能力,分布式数据库支持跨设备数据库访问能力。

应用创建的数据库,都保存到应用沙盒,当应用卸载时,数据库也会自动删除。

概述:

ArkData Kit(方舟数据管理)为开发者提供数据存储、数据管理和数据同步能力,比如联系人数据可以保存到数据库中,提供数据库的安全、可靠以及共享访问等管理机制,也支持与手表同步联系人信息。

应用数据持久化(三种方式)

应用数据持久化,是指应用将内存中的数据通过文件或数据库的形式保存到设备上。内存中的数据形态通常是任意的数据结构或数据对象,存储介质上的数据形态可能是文本、数据库、二进制文件等。HarmonyOS标准系统支持典型存储数据形态包括如下三类:

用户首选项(Preferences):通常用于保存应用的配置信息。数据通过文本的形式保存在设备中,应用使用过程中会将文本中的数据全量加载到内存中,所以访问速度快、效率高,但不适合需要存储大量数据的场景。

,选项都是唯一的,都是首选项。应用于应用的各种设置。

键值型数据库(KV-Store):一种非关系数据库(KV),其数据以“键值”对的形式进行组织、索引和存储,其中“键”作为唯一标识符。适合很少数据关系和业务关系的业务数据存储,尤其是分布式应用场景中。

(如:批量同种类型的数据,10月1号进账多少钱,10-1出账多少钱,10-2进出账多少钱,。。。很规律的数据)

关系型数据库(RelationalStore):一种关系型数据库(Table),以行和列(表格)的形式存储数据,广泛用于应用中的关系型数据的处理,包括一系列的增、删、改、查等接口,开发者也可以运行自己定义的SQL语句来满足复杂业务场景的需要。

(如我的联系人、收货地址、收货明细)

一、用户首选项

1、向首选项对象写出KV数据

let p = preferences.getPreferencesSync(getContext() , {name: 'myData01' // 首选项文件的名称} )
为什么得到首选项,要获取上下文呢?通过上下文能找到文件的沙箱目录,通过沙箱目录才能找到文件存到哪去。
因为首选项是一个全局的对象,所以需要获取上下文来获取首选项对象。

用户首选项持久化数据都是 Key-Value 对;Key非空且唯一,长度不能超过80个字节;Value允许为空,如果是字符串类型,必须采用UTF-8编码,长度不能超过8192个字节。

// 2、向首选项对象写出KV数据p.putSync("myBGColor", '#f00')p.putSync("autoStart", true)p.putSync("myBGColor", '#0f0')p.putSync("autoStart", 100)
// 3、刷新首选项对象
// 3、刷新首选项对象p.flushSync() // 刷新后,才能看到数据,把内存中的修改持久化到文件中
 // 刷新后,才能看到数据,把内存中的修改持久化到文件中  

完整代码:

Button('1、向首选项对象写出KV数据').onClick(()=>{//   1、先找到首选项对象let p = preferences.getPreferencesSync(getContext() , {name: 'myData01' // 首选项文件的名称} )/*为什么得到首选项,要获取上下文呢?通过上下文能找到文件的沙箱目录,通过沙箱目录才能找到文件存到哪去。因为首选项是一个全局的对象,所以需要获取上下文来获取首选项对象*/// 2、向首选项对象写出KV数据p.putSync("myBGColor", '#f00')p.putSync("autoStart", true)p.putSync("myBGColor", '#0f0')p.putSync("autoStart", 100)// 3、刷新首选项对象p.flushSync() // 刷新后,才能看到数据,把内存中的修改持久化到文件中  ctx.preferenceDir()console.log('---首选项数据写出完毕---')})

效果:

2、向首选项对象读取KV数据

//   1、先找到首选项对象
let p = preferences.getPreferencesSync(getContext(), {name: 'myData01' // 首选项文件的名称} )
  // 2、向首选项对象读取KV数据
// 2、向首选项对象读取KV数据let v0 = p.getSync("myFontSize", 12) // 如果没有这个key,就返回默认值12,如果有这个key,就返回这个key的值let v1 = p.getSync("myBGColor", '#fff')let v2 = p.getSync("autoStart", false)let v3 = p.getSync("proxy", 999)// p.flushSync() 不需要刷新,因为读取数据的时候,并没有修改数据console.log('---首选项数据读取完毕---')console.log('myFontSize:', v0, v1, v2, v3)
})

完整代码:

Button('2、向首选项对象读取KV数据').onClick(()=>{//   1、先找到首选项对象let p = preferences.getPreferencesSync(getContext(), {name: 'myData01' // 首选项文件的名称} )// 2、向首选项对象读取KV数据let v0 = p.getSync("myFontSize", 12) // 如果没有这个key,就返回默认值12,如果有这个key,就返回这个key的值let v1 = p.getSync("myBGColor", '#fff')let v2 = p.getSync("autoStart", false)let v3 = p.getSync("proxy", 999)// p.flushSync() 不需要刷新,因为读取数据的时候,并没有修改数据console.log('---首选项数据读取完毕---')console.log('myFontSize:', v0, v1, v2, v3)})

3、修改首选项中的数据

 //   1、先找到首选项对象
let p = preferences.getPreferencesSync(getContext(), {name: 'myData01' // 首选项文件的名称} )

2、修改首选项中的数据

p.putSync("myBGColor", '#ff000000')

3、完整代码

Button('3、修改首选项对象中的数据').onClick(()=>{//   1、先找到首选项对象let p = preferences.getPreferencesSync(getContext(), {name: 'myData01' // 首选项文件的名称} )// 2、向首选项对象修改数据p.putSync("myBGColor", '#ff000000')p.flushSync() // 刷新后,才能看到数据,把内存中的修改持久化到文件中  ctx.preferenceDir()console.log('首选项数据修改完成!')})

必须p.flush(),如果不冲刷,只有当前内存中加载的首选项被修改了,外存中的文件没有被修改。

(如不加flush,控制台显示修改成功,但重新启动项目,会发现数据的值又会变成修改前的数据。如果使用flush,重新启动,数据的值依旧为修改后的值)

4、删除首选项对象中的数据

 //   1、先找到首选项对象
let p = preferences.getPreferencesSync(getContext(), {name: 'myData01' // 首选项文件的名称} )

2、修改首选项中的数据

// 向首选项对象删除数据p.deleteSync("myBGColor");p.flushSync()

3、完整代码

Button('3、删除首选项对象中的数据').onClick(()=>{//   1、先找到首选项对象let p = preferences.getPreferencesSync(getContext(), {name: 'myData01' // 首选项文件的名称} )// 向首选项对象删除数据p.deleteSync("myBGColor");p.flushSync()console.log('首选项数据删除完成!');})

5、清空首选项中的数据(文件还在)

Button('5、清空首选项对象中的数据').onClick(()=>{//   1、先找到首选项对象let p = preferences.getPreferencesSync(getContext(), {name: 'myData01' // 首选项文件的名称} )// 向首选项对象删除数据p.clearSync()p.flushSync()console.log('首选项数据清空完成!')})

6、删除首选项文件(文件不在)

Button('5、删除首选项对象中的数据').onClick(async ()=>{await preferences.deletePreferences(getContext(), 'myData01')console.log('首选项数据删除完成!')})

二、键值型数据库

数据是有格式的话,用首选项(虽然是键值对,但不是无限多的)麻烦、如键-值。一般需要增删改查!

键值型数据库存储键值对形式的数据,当需要存储的数据没有复杂的关系模型,比如每日的流水账记录、当前用户每日的上班出勤记录等,由于数据复杂度低,更容易兼容不同数据库版本和设备类型,因此推荐使用键值型数据库持久化此类数据。

约束限制:

● 设备协同数据库,针对每条记录,Key的长度≤896 Byte,Value的长度<4 MB;

● 单版本数据库,针对每条记录,Key的长度≤1 KB,Value的长度<4 MB;

● 每个应用程序最多支持同时打开16个键值型分布式数据库;

● 键值型数据库事件回调方法中不允许进行阻塞操作,例如修改UI组件。

获取一个KVManager实例

若要使用键值型数据库,首先要获取一个KVManager实例,用于管理数据库对象。

// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})

创建并获取键值数据库。

//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})
securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4

安全级别

说明

S1

表示数据库的安全级别为低级别,数据的泄露、篡改、破坏、销毁可能会给个人或组织导致有限的不利影响。

例如,性别、国籍,用户申请记录等

S2

表示数据库的安全级别为中级别,数据的泄露、篡改、破坏、销毁可能会给个人或组织导致严重的不利影响。

例如,个人详细通信地址,姓名昵称等

S3

表示数据库的安全级别为高级别,数据的泄露、篡改、破坏、销毁可能会给个人或组织导致严峻的不利影响。

例如,个人实时精确定位信息、运动轨迹等

S4

表示数据库的安全级别为关键级别,业界法律法规中定义的特殊数据类型,涉及个人的最私密领域的信息或者一旦泄露、篡改、破坏、销毁可能会给个人或组织造成重大的不利影响数据。

例如,政治观点、宗教、和哲学信仰、工会成员资格、基因数据、生物信息、健康和性生活状况、性取向等或设备认证鉴权、个人的信用卡等财务信息


调用put()方法向键值数据库中插入数据

          db.put('20241001-IN', 3000)db.put('20241005-OUT', 1000)db.put('20241005-IN', 5000)db.put('20241010-OUT', 2000)db.put('20241015-OUT', 2000)db.put('20241015-OUT', 1000)console.log('---键值对存储完毕---')

说明

当Key值存在时,put()方法会修改其值,否则新增一条数据。

Button('1、保存键值对数据库').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})db.put('20241001-IN', 3000)db.put('20241005-OUT', 1000)db.put('20241005-IN', 5000)db.put('20241010-OUT', 2000)db.put('20241015-OUT', 2000)db.put('20241015-OUT', 1000)console.log('---键值对存储完毕---')})

putBatch()批量添加键值对数据

//   3、批量添加键值对数据库await db.putBatch([ //  批量添加键值对数据库{key:'20241001-IN', value: { type:5, value:2334 }},{key:'20241001-OUT', value: { type:5, value:3232 }},{key:'20241002-IN', value: { type:5, value:2234 }},{key:'20241002-OUT', value: { type:5, value:4543 }}])
Button('7、批量添加键值对数据库----putBatch()').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})//   3、批量添加键值对数据库await db.putBatch([ //  批量添加键值对数据库{key:'20241001-IN', value: { type:5, value:2334 }},{key:'20241001-OUT', value: { type:5, value:3232 }},{key:'20241002-IN', value: { type:5, value:2234 }},{key:'20241002-OUT', value: { type:5, value:4543 }}])console.log(' ---批量添加键值对数据库完毕---')})

调用get()方法获取指定键的值

          let v0 =  await db.get('20241001-IN')let v1 =  await db.get('20241005-OUT')let v2 =  await db.get('20241005-IN')let v3 =  await db.get('20241010-OUT')let v4 =  await db.get('20241015-OUT')
Button('2、读取键值对数据库').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})let v0 =  await db.get('20241001-IN')let v1 =  await db.get('20241005-OUT')let v2 =  await db.get('20241005-IN')let v3 =  await db.get('20241010-OUT')let v4 =  await db.get('20241015-OUT')console.log('---键值对数据读取完毕---', v0, v1, v2, v3, v4)})

完整代码:

import { distributedKVStore, preferences } from '@kit.ArkData';@Entry
@Component
struct Index {build() {Column({ space: 16 }) {Text('ArkData-键值对存储').fontSize(30)Button('1、保存键值对数据库').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})db.put('20241001-IN', 1000)db.put('20241005-OUT', 2000)db.put('20241005-IN', 3000)db.put('20241010-OUT', 4000)db.put('20241015-OUT', 5000)db.put('20241015-OUT', 6000)console.log('---键值对存储完毕---')})Button('2、读取键值对数据库').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})let v0 =  await db.get('20241001-IN')let v1 =  await db.get('20241005-OUT')let v2 =  await db.get('20241005-IN')let v3 =  await db.get('20241010-OUT')let v4 =  await db.get('20241015-OUT')console.log('---键值对数据读取完毕---', v0, v1, v2, v3, v4)})}.height('100%').width('100%')}
}

效果:

getEntries 获取匹配指定键前缀的所有键值对

//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})let list = await db.getEntries('2024') // 模糊查询,返回一个数组,查询以2024开头的所有键值对list.forEach((item)=>{console.log('<键:'+item.key, '值:'+JSON.stringify(item.value)+'>')})
Button('3、读取键值对数据库(2)').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})let list = await db.getEntries('2024') // 模糊查询,返回一个数组,查询以2024开头的所有键值对list.forEach((item)=>{console.log('<键:'+item.key, '值:'+JSON.stringify(item.value)+'>')})})

完整代码:

import { distributedKVStore, preferences } from '@kit.ArkData';@Entry
@Component
struct Index {build() {Column({ space: 16 }) {Text('ArkData-键值对存储').fontSize(30)Button('1、保存键值对数据库').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})db.put('20241001-IN', 1000)db.put('20241005-OUT', 2000)db.put('20241005-IN', 3000)db.put('20241010-OUT', 4000)db.put('20241015-OUT', 5000)db.put('20241015-OUT', 6000)console.log('---键值对存储完毕---')})Button('2、读取键值对数据库').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})let v0 =  await db.get('20241001-IN')let v1 =  await db.get('20241005-OUT')let v2 =  await db.get('20241005-IN')let v3 =  await db.get('20241010-OUT')let v4 =  await db.get('20241015-OUT')console.log('---键值对数据读取完毕---', v0, v1, v2, v3, v4)})Button('3、读取键值对数据库(2)').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})//   2、使用管理器创建KVStore对象let db: distributedKVStore.SingleKVStore = await mgr.getKVStore('myData02', {securityLevel: distributedKVStore.SecurityLevel.S1 // 安全等级 S1最普通安全级别 S2 S3 S4})let list = await db.getEntries('2024') // 模糊查询,返回一个数组,查询以2024开头的所有键值对list.forEach((item)=>{console.log('<键:'+item.key, '值:'+JSON.stringify(item.value)+'>')})})}.height('100%').width('100%')}
}

运行结果:

修改指定键值中的数据

//   3、修改键值对数据库await db.put('20241001-IN', 900) // 修改,既是添加,又是修改

调用delete()方法删除指定键值的数据

//   3、删除键值对数据库await db.delete('20241001-IN')

6、删除整个键值对数据库

await mgr.deleteKVStore('"com.swk.MyApplication11_09_morning"','myData02')
Button('6、删除整个键值对数据库').onClick(async () => {// 1、创建KVStore管理器对象let mgr = distributedKVStore.createKVManager({bundleName: "com.swk.MyApplication11_09_morning",context: getContext()})await mgr.deleteKVStore('"com.swk.MyApplication11_09_morning"','myData02')})

通过storeId的值删除指定的分布式键值数据库

三、通过关系型数据库实现数据持久化

1.向关系型数据库中写出数据

1.打开关系型数据库(没有的话,会自动创建数据库myData03)
let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1  // 安全级别
})
let sql = 'CREATE TABLE friends(fid INTEGER PRIMARY KEY AUTOINCREMENT, fname VARCHAR(32), salary FLOAT, isMarried INT )' 
// SQLite没有BOOLEAN类型,0表示0表示false,1表示true
// SQLite:INT类型无法自增,需要使用INTEGER类型 
// MYSQL自增:AUTO_INCREMENT, SQLite自增:AUTOINCREMENT


2、如果不存在“我的联系人”表的话,就创建它
if (db.version === 0) {//   数据的版本号为0,说明数据库还没有创建表,需要创建表let sql = 'CREATE TABLE friends(fid INTEGER PRIMARY KEY AUTOINCREMENT, fname VARCHAR(32), salary FLOAT, isMarried INT )' // SQLite没有BOOLEAN类型,0表示0表示false,1表示truedb.executeSql(sql)} else if (db.version === 1) {//   数据的版本号为1,说明数据库已经创建了表,不需要创建表,此处可以再创建表}

3、向“我的联系人表中”插入数据
//   3、向“我的联系人表中”插入数据let rid1 = db.insertSync("friends", {fid:1, fname:'汤姆', salary: 18000, isMarried:0})console.log('---一行数据插入成功!行号为:', rid1)let rid2 = db.insertSync("friends", {fid:5, fname:'杰瑞', salary: 20000, isMarried:1})console.log('---一行数据插入成功!行号为:', rid2)let rid3 = db.insertSync("friends", {fid:8, fname:'玛丽', salary: 8000, isMarried:1})console.log('---一行数据插入成功!行号为:', rid3)let rid4 = db.insertSync("friends", {fid:12, fname:'琼斯', salary: 12000, isMarried:0})console.log('---一行数据插入成功!行号为:', rid4)//   4、关闭关系型数据库console.log('---关系型数据库刷新完毕---')await db.close()

完整代码:

import { distributedKVStore, preferences, relationalStore } from '@kit.ArkData';
import List from '@ohos.util.List';@Entry
@Component
struct Index {build() {Column({ space: 16 }) {Text('ArkData Kit - 关系型数据库存储').fontSize(30)Button('1.向关系型数据库中写出数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})//   2、如果不存在“我的联系人”表的话,就创建它if (db.version === 0) {//   数据的版本号为0,说明数据库还没有创建表,需要创建表let sql = 'CREATE TABLE friends(fid INTEGER PRIMARY KEY AUTOINCREMENT, fname TEXT, salary REAL, isMarried NUMERIC )' // SQLite没有BOOLEAN类型,0表示0表示false,1表示true// SQLite中 :INT类型无法自增,需要使用INTEGER类型// MYSQL自增:AUTO_INCREMENT, SQLite自增:AUTOINCREMENT// MySQL中的TEXT类型:指大型文本列,在SQLite中是TEXT类型指任何文本类型// MYSQL中有BOOLEAN类型,SQLite中没有BOOLEAN类型,推荐使用NUMERIC,0表示false,1表示truedb.executeSql(sql)} else if (db.version === 1) {//   数据的版本号为1,说明数据库已经创建了表,不需要创建表,此处可以再创建表}//   3、向“我的联系人表中”插入数据let rid1 = db.insertSync("friends", {fid:1, fname:'汤姆', salary: 18000, isMarried:0})console.log('---一行数据插入成功!行号为:', rid1)let rid2 = db.insertSync("friends", {fid:null, fname:'杰瑞', salary: 20000, isMarried:1})console.log('---一行数据插入成功!行号为:', rid2)let rid3 = db.insertSync("friends", {fid:8, fname:'玛丽', salary: 8000, isMarried:1})console.log('---一行数据插入成功!行号为:', rid3)let rid4 = db.insertSync("friends", {fid:null, fname:'琼斯', salary: 12000, isMarried:0})console.log('---一行数据插入成功!行号为:', rid4)//   4、关闭关系型数据库console.log('---关系型数据库刷新完毕---')await db.close()})}.height('100%').width('100%')}
}

效果:


2、删除

Button('2.删除关系型数据库中的数据行').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})// 2、删除指定编号的好友信息let p = new relationalStore.RdbPredicates("friends")let num = db.deleteSync(p.equalTo("fid", 1))console.log(`---删除了${num}行数据---`)await db.close()})

3、修改关系型数据库的数据

// 2、修改制定编号的好友信息let p = new relationalStore.RdbPredicates("friends")  // 谓词,相当于SQL中的where条件,查询的表名let num = db.updateSync({fname:"乔伊斯", salary: 10002}, p.equalTo("fid", 9))  // 修改指定编号的好友信息console.log('---修改了'+num+'行数据---')
Button('3.修改关系型数据库中的数据行').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1 // 安全级别 S1最普通安全级别 S2 S3 S4})// 2、修改制定编号的好友信息let p = new relationalStore.RdbPredicates("friends")  // 谓词,相当于SQL中的where条件,查询的表名let num = db.updateSync({fname:"乔伊斯", salary: 10002}, p.equalTo("fid", 9))  // 修改指定编号的好友信息console.log('---修改了'+num+'行数据---')await db.close()})

4-1 查询关系型数据库的所有行数据

Button('4-1.查询关系型数据库中的所有行数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {  // 打开关系型数据库name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})// 2、向关系型数据库中发出查询语句// let sql = 'SELECT fid,fname,salary FROM friends'     // 写法一:指定列let sql = 'SELECT * FROM friends'let rs = db.querySqlSync(sql)  // 查询语句的结果集,是一个二维数组,每一行是一个数组,每一列是一个数组的元素,每一行的列数是一样的console.log('查询到数据了,总共的数据行数:', rs.rowCount)await db.close()})
let rs = db.querySqlSync(sql)  

查询语句的结果集,是一个二维数组,每一行是一个数组,每一列是一个数组的元素,每一行的列数是一样的


// 3、遍历结果集,把每一行的数据都打印出来,使用rs对象的getXXX()方法获取每一行的数据while  (rs.goToNextRow()) { // 获取下一行数据,如果有数据,返回true,如果没有数据,返回falseconsole.log('---', rs.getLong(0), rs.getString(1), rs.getDouble(2), rs.getDouble(3)) // 0表示第一列fid,1表示第二列fname,2表示第三列salary, 3表示第四列isMarried}

查询代码

Button('4-1.查询关系型数据库中的所有行数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {  // 打开关系型数据库name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})// 2、向关系型数据库中发出查询语句// let sql = 'SELECT fid,fname,salary FROM friends'     // 写法一:指定列let sql = 'SELECT * FROM friends'let rs = db.querySqlSync(sql)  // 查询语句的结果集,是一个二维数组,每一行是一个数组,每一列是一个数组的元素,每一行的列数是一样的console.log('查询到数据了,总共的数据行数:', rs.rowCount)// 3、遍历结果集,把每一行的数据都打印出来,使用rs对象的getXXX()方法获取每一行的数据while  (rs.goToNextRow()) { // 获取下一行数据,如果有数据,返回true,如果没有数据,返回falseconsole.log('---', rs.getLong(0), rs.getString(1), rs.getDouble(2), rs.getDouble(3)) // 0表示第一列fid,1表示第二列fname,2表示第三列salary, 3表示第四列isMarried}await db.close()})

注意:这里是确定数据库 myData03 肯定存在,所有没有判断它是否为0的语句。

完整代码:

import { distributedKVStore, preferences, relationalStore } from '@kit.ArkData';
import List from '@ohos.util.List';@Entry
@Component
struct Index {build() {Column({ space: 16 }) {Text('ArkData Kit - 关系型数据库存储').fontSize(30)Button('1.向关系型数据库中写出数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})//   2、如果不存在“我的联系人”表的话,就创建它if (db.version === 0) {//   数据的版本号为0,说明数据库还没有创建表,需要创建表let sql = 'CREATE TABLE friends(fid INTEGER PRIMARY KEY AUTOINCREMENT, fname TEXT, salary REAL, isMarried NUMERIC )' // SQLite没有BOOLEAN类型,0表示0表示false,1表示true// SQLite中 :INT类型无法自增,需要使用INTEGER类型// MYSQL自增:AUTO_INCREMENT, SQLite自增:AUTOINCREMENT// MySQL中的TEXT类型:指大型文本列,在SQLite中是TEXT类型指任何文本类型// MYSQL中有BOOLEAN类型,SQLite中没有BOOLEAN类型,推荐使用NUMERIC,0表示false,1表示trueawait db.executeSql(sql)} else if (db.version === 1) {//   数据的版本号为1,说明数据库已经创建了表,不需要创建表,此处可以再创建表}//   3、向“我的联系人表中”插入数据let rid1 = db.insertSync("friends", {fid:1, fname:'汤姆', salary: 18000, isMarried:0})console.log('---一行数据插入成功!行号为:', rid1)let rid2 = db.insertSync("friends", {fid:null, fname:'杰瑞', salary: 20000, isMarried:1})console.log('---一行数据插入成功!行号为:', rid2)let rid3 = db.insertSync("friends", {fid:8, fname:'玛丽', salary: 8000, isMarried:1})console.log('---一行数据插入成功!行号为:', rid3)let rid4 = db.insertSync("friends", {fid:null, fname:'琼斯', salary: 12000, isMarried:0})console.log('---一行数据插入成功!行号为:', rid4)//   4、关闭关系型数据库console.log('---关系型数据库刷新完毕---')await db.close()})Button('4-1.查询关系型数据库中的所有行数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {  // 打开关系型数据库name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})// 2、向关系型数据库中发出查询语句// let sql = 'SELECT fid,fname,salary FROM friends'     // 写法一:指定列let sql = 'SELECT * FROM friends'let rs = db.querySqlSync(sql)  // 查询语句的结果集,是一个二维数组,每一行是一个数组,每一列是一个数组的元素,每一行的列数是一样的console.log('查询到数据了,总共的数据行数:', rs.rowCount)// 3、遍历结果集,把每一行的数据都打印出来,使用rs对象的getXXX()方法获取每一行的数据while  (rs.goToNextRow()) { // 获取下一行数据,如果有数据,返回true,如果没有数据,返回falseconsole.log('---', rs.getLong(0), rs.getString(1), rs.getDouble(2), rs.getDouble(3)) // 0表示第一列fid,1表示第二列fname,2表示第三列salary, 3表示第四列isMarried}await db.close()})}.height('100%').width('100%')}
}

效果:


4-1-2

Button('4-1-2.查询关系型数据库中的所有行数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {  // 打开关系型数据库name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})// 2、向关系型数据库中发出查询谓词let p = new relationalStore.RdbPredicates("friends") // From friends// let rs = db.querySync(p)let rs = db.querySync(p, ['fid', 'fname', 'salary', 'isMarried']) // 可以指定列, 如果不指定列,默认查询所有列, 列名的顺序必须和查询语句中的列名的顺序一致console.log('查询到数据了,总共的数据行数:', rs.rowCount)// 3、遍历结果集,把每一行的数据都打印出来,使用rs对象的getXXX()方法获取每一行的数据while  (rs.goToNextRow()) { // 获取下一行数据,如果有数据,返回true,如果没有数据,返回falseconsole.log('---', rs.getLong(0), rs.getString(1), rs.getDouble(2), rs.getDouble(3)) // 0表示第一列fid,1表示第二列fname,2表示第三列salary, 3表示第四列isMarried}await db.close()})

4-2 查询关系型数据库中的某一行数据

//   2、向关系型数据库中发出查询语句let sql = 'SELECT fid,fname,salary,isMarried FROM friends where fid = 9'      // 写法一:指定列let rs = db.querySqlSync(sql)console.log('查询到数据了,总共的数据行数:', rs.rowCount)if  (rs.goToNextRow()) { // 获取下一行数据,如果有数据,返回true,如果没有数据,返回falseconsole.log('---', rs.getLong(0), rs.getString(1), rs.getDouble(2), rs.getDouble(3)) // 0表示第一列fid,1表示第二列fname,2表示第三列salary, 3表示第四列isMarried} else {console.log('根据您提供的好友编号,没有找到好友!')}await db.close()})
let sql = 'SELECT fid,fname,salary,isMarried FROM friends where fid = 9'

where 条件判定

 注意:要防止SQL注入:(用户的输入绝不可以用 加法 拼接)

描述:用户的输入如果直接拼接到字符串中,可能会影响判定。

如:一系统用户名:root, 密码:123456 ,判定条件为

select * from table where uname =账户 and upwd = 密码

如果用户在登入时,账户输入正确为root,但密码忘记,却用"  ' or ' 1' = '1'  '  ",可能登入成功。

因为此时判断语句为

select * from table where uname =“root ” and upwd = ' ' or ' 1' = '1'  ' '

import { distributedKVStore, preferences, relationalStore } from '@kit.ArkData';
import List from '@ohos.util.List';@Entry
@Component
struct Index {build() {Column({ space: 16 }) {Text('ArkData Kit - 关系型数据库存储').fontSize(30)Button('1.向关系型数据库中写出数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})//   2、如果不存在“我的联系人”表的话,就创建它if (db.version === 0) {//   数据的版本号为0,说明数据库还没有创建表,需要创建表let sql = 'CREATE TABLE friends(fid INTEGER PRIMARY KEY AUTOINCREMENT, fname TEXT, salary REAL, isMarried NUMERIC )' // SQLite没有BOOLEAN类型,0表示0表示false,1表示true// SQLite中 :INT类型无法自增,需要使用INTEGER类型// MYSQL自增:AUTO_INCREMENT, SQLite自增:AUTOINCREMENT// MySQL中的TEXT类型:指大型文本列,在SQLite中是TEXT类型指任何文本类型// MYSQL中有BOOLEAN类型,SQLite中没有BOOLEAN类型,推荐使用NUMERIC,0表示false,1表示trueawait db.executeSql(sql)} else if (db.version === 1) {//   数据的版本号为1,说明数据库已经创建了表,不需要创建表,此处可以再创建表}//   3、向“我的联系人表中”插入数据let rid1 = db.insertSync("friends", {fid:1, fname:'汤姆', salary: 18000, isMarried:0})console.log('---一行数据插入成功!行号为:', rid1)let rid2 = db.insertSync("friends", {fid:null, fname:'杰瑞', salary: 20000, isMarried:1})console.log('---一行数据插入成功!行号为:', rid2)let rid3 = db.insertSync("friends", {fid:8, fname:'玛丽', salary: 8000, isMarried:1})console.log('---一行数据插入成功!行号为:', rid3)let rid4 = db.insertSync("friends", {fid:null, fname:'琼斯', salary: 12000, isMarried:0})console.log('---一行数据插入成功!行号为:', rid4)//   4、关闭关系型数据库console.log('---关系型数据库刷新完毕---')await db.close()})Button('2.删除关系型数据库中的数据行').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})//   2、如果不存在“我的联系人”表的话,就创建它if (db.version === 0) {//   数据的版本号为0,说明数据库还没有创建表,需要创建表let sql = 'CREATE TABLE friends(fid INTEGER PRIMARY KEY AUTOINCREMENT, fname TEXT, salary REAL, isMarried NUMERIC )' // SQLite没有BOOLEAN类型,0表示0表示false,1表示trueawait db.executeSql(sql)} else if (db.version === 1) {//   数据的版本号为1,说明数据库已经创建了表,不需要创建表,此处可以再创建表}await db.close()})Button('3.删除关系型数据库中的数据行').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})//   2、如果不存在“我的联系人”表的话,就创建它if (db.version === 0) {//   数据的版本号为0,说明数据库还没有创建表,需要创建表let sql = 'CREATE TABLE friends(fid INTEGER PRIMARY KEY AUTOINCREMENT, fname TEXT, salary REAL, isMarried NUMERIC )' // SQLite没有BOOLEAN类型,0表示0表示false,1表示trueawait db.executeSql(sql)} else if (db.version === 1) {//   数据的版本号为1,说明数据库已经创建了表,不需要创建表,此处可以再创建表}await db.close()})Button('4-1.查询关系型数据库中的所有行数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {  // 打开关系型数据库name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})// 2、向关系型数据库中发出查询语句let sql = 'SELECT fid,fname,salary,isMarried FROM friends'     // 写法一:指定列// let sql = 'SELECT * FROM friends'let rs = db.querySqlSync(sql)  // 查询语句的结果集,是一个二维数组,每一行是一个数组,每一列是一个数组的元素,每一行的列数是一样的console.log('查询到数据了,总共的数据行数:', rs.rowCount)// 3、遍历结果集,把每一行的数据都打印出来,使用rs对象的getXXX()方法获取每一行的数据while  (rs.goToNextRow()) { // 获取下一行数据,如果有数据,返回true,如果没有数据,返回falseconsole.log('---', rs.getLong(0), rs.getString(1), rs.getDouble(2), rs.getDouble(3)) // 0表示第一列fid,1表示第二列fname,2表示第三列salary, 3表示第四列isMarried}await db.close()})Button('4-2.查询关系型数据库中的某行数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})//   2、向关系型数据库中发出查询语句let id = 9;// let sql = 'SELECT fid,fname,salary,isMarried FROM friends where fid + i'      // SQL注入,拼接let sql = 'SELECT fid,fname,salary,isMarried FROM friends where fid = ?'      // 正确写法let rs = db.querySqlSync(sql, [id])console.log('查询到数据了,总共的数据行数:', rs.rowCount)if  (rs.goToNextRow()) { // 获取下一行数据,如果有数据,返回true,如果没有数据,返回falseconsole.log('---', rs.getLong(0), rs.getString(1), rs.getDouble(2), rs.getDouble(3)) // 0表示第一列fid,1表示第二列fname,2表示第三列salary, 3表示第四列isMarried} else {console.log('根据您提供的好友编号,没有找到好友!')}await db.close()})}.height('100%').width('100%')}
}


4-2-2 谓词查询


Button('4-2-2.查询关系型数据库中的某行数据').onClick(async () => {//   1、打开关系型数据库(没有的话,会自动创建数据库myData03)let db = await relationalStore.getRdbStore(getContext(), {name: 'myData03',securityLevel: relationalStore.SecurityLevel.S1})//   2、向关系型数据库中发出查询语句let p = new relationalStore.RdbPredicates("friends")      // 正确写法p.equalTo("fid", 9)  // WHERE fid = ?,天然防止SQL注入let rs = db.querySync(p)console.log('查询到数据了,总共的数据行数:', rs.rowCount)if  (rs.goToNextRow()) { // 获取下一行数据,如果有数据,返回true,如果没有数据,返回falseconsole.log('---', rs.getLong(0), rs.getString(1), rs.getDouble(2), rs.getDouble(3)) // 0表示第一列fid,1表示第二列fname,2表示第三列salary, 3表示第四列isMarried} else {console.log('根据您提供的好友编号,没有找到好友!')}await db.close()})

相关文章:

缓存和客户端数据存储体系(Ark Data Kit)--- 应用数据持久化(首选项持久化、K-V、关系型数据库)持续更新中...

Core File Kit做怎删改查操作不便&#xff0c;用Ark Data Kit。 功能介绍 ArkData &#xff08;方舟数据管理&#xff09;为开发者提供数据存储、数据管理和数据同步能力&#xff0c;比如联系人应用数据可以保存到数据库中&#xff0c;提供数据库的安全、可靠以及共享访问等管…...

ES 使用geo point 查询离目标地址最近的数据

需求描述&#xff1a;项目中需要通过经纬度坐标查询目标地所在的行政区。 解决思路大致有种&#xff0c;使用es和mysql分别查询。 1、使用es进行查询 将带有经纬度坐标的省市区数据存入es中&#xff0c;mappings字段使用geo point类型&#xff0c;索引及查询dsl如下。 geo p…...

本地部署OpenManus及原理介绍

概述&#xff1a; 最近Minaus特别火&#xff0c;随后开源社区就有项目尝试复刻Minaus&#xff0c;项目名称为OpenManus&#xff0c;原理是用推理模型为决策者&#xff0c;将我们输入的问题进行分解后调用本地工具执行。 OpenManus安装&#xff1a; 本人在Ubuntu桌面版本上安装…...

高效手机检测:视觉分析技术的优势

在当今社会&#xff0c;手机已成为人们日常生活和工作中不可或缺的工具。然而&#xff0c;在某些特定场合&#xff0c;如考场、工作场所等&#xff0c;手机的使用却可能带来负面影响。因此&#xff0c;如何有效监测和防止在这些场合偷用手机的行为&#xff0c;成为了一个亟待解…...

Java 多线程编程:提升系统并发处理能力!

多线程是 Java 中实现并发任务执行的关键技术&#xff0c;能够显著提升程序在多核处理器上的性能以及处理多任务的能力。本文面向初级到中级开发者&#xff0c;从多线程的基本定义开始&#xff0c;逐步讲解线程创建、状态管理、同步机制、并发工具以及新兴的虚拟线程技术。每部…...

Linux实时内核稳定性案例

稳定性问题分析 RT_RUNTIME_SHARE案例死锁问题Linux-rt下卡死之hrtimer分析Linux内核宕机案例 -mmap空指针Linux Hung Task分析过程...

解决 VSCode SSH 连接报错:“REMOTE HOST IDENTIFICATION HAS CHANGED” 的问题

问题描述 在使用 VSCode 通过 SSH 连接远程服务器时&#xff0c;我们可能会遇到类似如下的错误日志&#xff1a; WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! ... Offending ED25519 key in C:\Users\DELL/…...

Spring Boot配置类原理、Spring Boot核心机制理解,以及实现自动装置的底层原理

目的:从底层源码角度分析 Spring Boot 配置类以及自动装载的底层原理 文章目录 1. Spring Boot 配置类实现自动装载1.1 @Configuration注解1.2 @Configuration 注解完成 bean 注入流程图1.3 @ConfigurationProperties注解赋值2. Spring Boot的核心机制:自动装配2.1 @SpringBo…...

淘宝API vs 爬虫:合规获取实时商品数据的成本与效率对比

以下是淘宝 API 和爬虫在合规获取实时商品数据方面的成本与效率对比&#xff1a; 成本对比 淘宝 API 开发成本&#xff1a;需要申请开发者账号并获取 API 权限&#xff0c;部分敏感或高频访问的接口可能需要额外的审核或付费。开发过程中需要按照平台规定进行编程&#xff0c;相…...

01-Canvas-使用fabric初始

fabric官网&#xff1a; https://fabric5.fabricjs.com/demos/ 创建画布并绘制 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-sca…...

CMake简单入门

简介 CMake 是一个开源的跨平台构建系统生成工具&#xff0c;旨在简化和自动化项目的构建过程。它主要用于管理和控制软件构建的过程&#xff0c;特别是在处理复杂的项目结构和多个平台时。CMake 并不直接进行编译或链接&#xff0c;而是生成本地构建系统所需的文件&#xff0…...

树莓派 连接 PlutoSDR 教程

在树莓派5上安装PlutoSDR&#xff08;ADALM-Pluto&#xff09;的驱动程序&#xff0c;主要需要安装相关的库和工具&#xff0c;以便与PlutoSDR通信&#xff0c;比如libiio和libad9361&#xff0c;并确保系统能够识别设备。由于树莓派5运行的是基于Linux的系统&#xff08;通常是…...

【时时三省】(C语言基础)用printf函数输出数据3

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 ( 5 ) e格式符。 用格式声明%e指定以指数形式输出实数。如果不指定输出数据所占的宽度和数字部分的小数位数&#xff0c;许多C编译系统&#xff08;如VisualC&#xff09;会自动给出数字部分…...

Git使用(二)--如何配置 GitHub 远程仓库及本地 Git 环境

在日常的开发过程中&#xff0c;使用版本控制工具 Git 是一个非常重要的技能&#xff0c;特别是对于管理和协作开发。通过 GitHub&#xff0c;我们可以轻松地进行代码版本管理和共享。这篇博客将带您一步步学习如何配置 Git 环境并将本地仓库与 GitHub 远程仓库连接起来。 一、…...

在Pycharm配置conda虚拟环境的Python解释器

〇、前言 今天在配置python解释器时遇到了这样的问题 经过一下午自行摸索、上网搜寻后&#xff0c;终于找到的解决的方案&#xff0c;遂将该方法简要的记录下来&#xff0c;以备后用&#xff0c;并希望能帮助到有同样问题或需求的朋友:) 我所使用的软件的版本如下&#xff0c;假…...

CURL一文通

文章目录 1.什么是curl2.curl可以发送什么请求3.常见curl发http相关请求怎么写4.curl带上的参数分别有什么&#xff0c;可以怎么用5.进阶用法6.常见错误以及学习指导建议 1.什么是curl 是利用URL语法在命令行下工作的开源文件传输工具。尤其被广泛应用的在linux系统下。 2.cu…...

零基础keil:设置注释快捷键

1.打开快捷键设置&#xff1a; 在Keil中&#xff0c;选择菜单栏中的“Settings”&#xff0c;然后选择“Shortcuts”来打开快捷键设置界面。 2.选择注释命令&#xff1a; 在快捷键设置界面中&#xff0c;找到与注释相关的命令&#xff0c;如“Comment Selection”&#xff0…...

Java中关于Optional的 orElse 操作,以及 orElse 与 orElseGet 的区别

文章目录 1. 大概说明2. 详细分析2.1 .orElse 操作2.2 .orElse 的作用&#xff1a;避免空指针异常2.3 为什么要用&#xff1f;2.4 orElseGet如何使用2.5 orElse和orElseGet的区别 1. 大概说明 这篇文章的目的是为了说明&#xff1a; orElse 如何使用orElseGet 如何使用两者的…...

TCP/IP协议中三次握手(Three-way Handshake)与四次挥手(Four-way Wave)

TCP/IP协议中三次握手&#xff08;Three-way Handshake&#xff09;与四次挥手&#xff08;Four-way Wave&#xff09; 一、TCP三次握手&#xff08;Three-way Handshake&#xff09;二、TCP四次挥手&#xff08;Four-way Wave&#xff09;三、常见问题解答总结为什么三次握手不…...

python学智能算法(八)|决策树

【1】引言 前序学习进程中&#xff0c;已经对KNN邻近算法有了探索&#xff0c;相关文章链接为&#xff1a; python学智能算法&#xff08;七&#xff09;|KNN邻近算法-CSDN博客 但KNN邻近算法有一个特点是&#xff1a;它在分类的时候&#xff0c;不能知晓每个类别内事物的具…...

【经验】Orin系列Ubuntu远程桌面:VNC、NoMachine、URDC

1、VNC 1.1 Ubuntu端 1)安装VNC服务器 sudo apt install tigervnc-standalone-server2)安装xfce4 桌面 xfce4 用资源较GNOME ,KDE较少。适合老机器,轻量级桌面。与windows界面环境类似。 sudo apt install xfce4 xfce4-goodies也可以使用其它的桌面系统,可以使用如下命…...

【QT:控件】

目录 控件状态&#xff1a;​编辑 geometry : window frame windowlcon: qrc机制 qrc的使用方式&#xff1a; window opacity cursor font: ToolTip focusPolicy: styleSheet: 按钮类控件&#xff1a; PushButton: 给按钮添加图标&#xff1a; 给按钮添加快捷键…...

Python(最新版)集成开发环境PyCharm下载安装详细教程

Python 下载和安装 1.进入Python官网 Download Python | Python.org&#xff0c;点击Downloads&#xff0c;这里以Windows为例 2.选择下载Python 3.13.2 Windows 64位的版本。注意&#xff1a;不能在Windows 7 或更早的版本上使用。 3.打开文件&#xff0c;会自动出现安装界…...

PyTorch 实现 Conditional DCGAN(条件深度卷积生成对抗网络)进行图像到图像转换的示例代码

以下是一个使用 PyTorch 实现 Conditional DCGAN&#xff08;条件深度卷积生成对抗网络&#xff09;进行图像到图像转换的示例代码。该代码包含训练和可视化部分&#xff0c;假设输入为图片和 4 个工艺参数&#xff0c;根据这些输入生成相应的图片。 1. 导入必要的库 import …...

【BERT和GPT的区别】

BERT采用完形填空&#xff08;Masked Language Modeling, MLM&#xff09;与GPT采用自回归生成&#xff08;Autoregressive Generation&#xff09;的差异&#xff0c;本质源于两者对语言建模的不同哲学导向与技术目标的根本分歧。这种选择不仅塑造了模型的架构特性&#xff0c…...

PTA 7-12 排序

题目描述 给定 n 个&#xff08;长整型范围内的&#xff09;整数&#xff0c;要求输出从小到大排序后的结果。 本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下&#xff1a; 数据1&#xff1a;只有1个元素&#xff1b;数据2&#xff1a;11个不…...

uniapp 实现的步进指示器组件

采用 uniapp 实现的一款步进指示器组件&#xff0c;展示业务步骤进度等内容&#xff0c;对外提供“前进”、“后退”方法&#xff0c;让用户可高度自定义所需交互&#xff0c;适配 web、H5、微信小程序&#xff08;其他平台小程序未测试过&#xff0c;可自行尝试&#xff09; 可…...

大模型-提示词调优

什么是提示词 提示词&#xff08;Prompt&#xff09;在大模型应用中扮演着关键角色&#xff0c;它是用户输入给模型的一段文本指令 。简单来说&#xff0c;就是我们向大模型提出问题、请求或描述任务时所使用的文字内容。例如&#xff0c;当我们想让模型写一篇关于春天的散文&a…...

【k8s002】k8s健康检查与故障诊断

k8s健康检查与故障诊断 ‌一、集群状态检查‌ ‌检查节点健康状态‌ kubectl get nodes -o wide # 查看节点状态及基本信息 kubectl describe node <node-name> # 分析节点详细事件&#xff08;如资源不足、网络异常&#xff09; kubectl top nodes …...

统计数字字符个数(信息学奥赛一本通-1129)

【题目描述】 输入一行字符&#xff0c;统计出其中数字字符的个数。 【输入】 一行字符串&#xff0c;总长度不超过255。 【输出】 输出为1行&#xff0c;输出字符串里面数字字符的个数。 【输入样例】 Peking University is set up at 1898. 【输出样例】 4 【输出样例】 #in…...