【HarmonyOS】网络数据请求连接与数据持久化操作

news2025/2/25 18:08:28

            从今天开始,博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”,对于刚接触这项技术的小伙伴在学习鸿蒙开发之前,有必要先了解一下鸿蒙,从你的角度来讲,你认为什么是鸿蒙呢?它出现的意义又是什么?鸿蒙仅仅是一个手机操作系统吗?它的出现能够和Android和IOS三分天下吗?它未来的潜力能否制霸整个手机市场呢?

抱着这样的疑问和对鸿蒙开发的好奇,让我们开始今天对网络连接和数据持久化的掌握吧!

目录

网络连接

HTTP数据请求

HTTP数据请求(第三方库axios)

ohpm安装使用教程

axios第三方库安装

axios的使用

数据持久化

用户首选项

关系型数据库


网络连接

在harmonyos中提供了三种不同的网络连接方式,如下图所示,接下来我们对这三种不同的网络连接方式进行一个简单的讲解,我们可以根据自身的需求去选择合适的方式,但事实上我们在开发过程中,最后两种使用的情况比较少,最常见的就是http的数据请求方式。我们这里也就拿http数据请求这个例子进行讲解使用:

HTTP数据请求

是由客户端向服务端发起的一种单向的连接方式,接下来就这种连接方式进行一个简单的讲解,如果我们想发送http请求服务,需要遵循以下的步骤来进行:

1)导入 http 模块:

import http from '@ohos.net.http';

2)使用http模块发送请求,处理响应:

// 创建一个http的请求对象,不可复用
let httpRequest = http.createHttp()
// 发送网络请求
httpRequest.request(
  'http://localhost:3000/user', // 请求的URL路径
  { // 请求选项 HttpRequestOptions
    method: http.RequestMethod.GET,
    extraData: { 'param1': 'value1' },
  }
)

关于 HttpRequestOptions 的选择,可以参考下面的表格:

名称类型描述
methodRequestMethod请求方式:GET、POST、PUT、DELETE等
extraDatastring|Object请求参数
headerObject请求头字段
connectTimeoutnumber连接超时时间,单位毫秒,默认是60000ms
readTimeoutnumber读取超时时间,单位毫秒,默认是60000ms

3)处理响应的结果

// 创建一个http的请求对象,不可复用
let httpRequest = http.createHttp()
// 发送网络请求
httpRequest.request(
  'http://localhost:3000/user', // 请求的URL路径
  { // 请求选项 HttpRequestOptions
    method: http.RequestMethod.GET,
    extraData: { 'param1': 'value1' },
  }
)
  // 处理响应结果
  .then((resp: http.HttpResponse) => {
    if(resp.responseCode === 200){
      // 请求成功
    }
  })
  .catch((err: Error) => {
    // 请求失败
  })

关于 HttpResponse 的选择,可以参考下面的表格:

名称类型描述
responseCodeResponseCode响应状态码
headerObject响应头
cookiesstring响应返回的cookies
resultstring | Object响应体,默认是JSON字符串
resultTypeHttpDataType返回值类型

ok,接下来我们通过上面给出的步骤来开始编写相应的接口来获取数据,接口地址就使用网上公共的接口地址吧,通过新建ts文件,将接口函数进行书写:

import http from '@ohos.net.http';

class getAPI {
  BaseCatURL = 'https://api.thecatapi.com/v1/images' // 猫图
  catNum = 2 // 猫数

  // 获取猫的图片
  getCat(){
    return new Promise((resolve, reject) => {
      // 创建一个http的请求对象,不可复用
      let httpRequest = http.createHttp()
      // 发送网络请求
      httpRequest.request(
        `${this.BaseCatURL}/search?limit=${this.catNum}`,// 请求的URL路径
        { // 请求选项 HttpRequestOptions
          method: http.RequestMethod.GET,
        }
      )
        // 处理响应结果
        .then((resp: http.HttpResponse) => {
          if(resp.responseCode === 200){
            // 请求成功
            resolve(JSON.parse(resp.result.toString()))
          }else{
            console.log('查询信息失败!', JSON.stringify(resp))
            reject('查询信息失败!')
          }
        })
        .catch((err: Error) => {
          // 请求失败
          console.log('查询信息失败!', JSON.stringify(err))
          reject('查询信息失败!')
        })
    })
  }

  // 获取猫的图片
  getWord(){
    return new Promise((resolve, reject) => {
      // 创建一个http的请求对象,不可复用
      let httpRequest = http.createHttp()
      // 发送网络请求
      httpRequest.request(
        'http://api.uomg.com/api/rand.qinghua',// 请求的URL路径
        { // 请求选项 HttpRequestOptions
          method: http.RequestMethod.GET,
        }
      )
        // 处理响应结果
        .then((resp: http.HttpResponse) => {
          if(resp.responseCode === 200){
            console.log(resp.result.toString())
            // 请求成功
            resolve(JSON.parse(resp.result.toString()))
          }else{
            console.log('查询信息失败!', JSON.stringify(resp))
            reject('查询信息失败!')
          }
        })
        .catch((err: Error) => {
          // 请求失败
          console.log('查询信息失败!', JSON.stringify(err))
          reject('查询信息失败!')
        })
    })
  }
}

const getApi = new getAPI()
export default getApi

接下来在ets文件调用接口函数,使用aboutToAppear函数,在页面还未加载完成获取相应的数据并渲染到界面上,如下:

import getApi from '../api/test'

@Entry
@Component
struct test {
  @State catInfo: any = []
  @State word: string = ''
  scroller: Scroller = new Scroller()
  aboutToAppear(){
    this.loadCatInfo()
  }
  build() {
    Column(){
      Text('猫猫的图片')
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
        .margin(15)

      Text('今日情话:'+ this.word)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin(5)
      Divider()
        .margin(10)
      Grid(this.scroller){
        ForEach(this.catInfo, (item: any) => {
          GridItem(){
            Image(item.url)
              .width('100%')
              .objectFit(ImageFit.Auto)
              .height(120)
          }
        })
      }
      .width('100%')
      .columnsTemplate(`1fr 1fr`)
      .columnsGap(10)
      .rowsGap(10)
      .padding(5)
      .height(540)
    }
    .padding(10)

    .width('100%')
    .height('100%')
  }
  loadCatInfo() {
    // 加载数据
    getApi.getCat()
      .then((res: any) => {
        this.catInfo = res
      })
    getApi.getWord()
      .then((res: any) => {
        console.log('111',res.content)
        this.word = res.content
      })
  }
}

最终呈现的效果如下:

HTTP数据请求(第三方库axios)

上面我们讲解了如何利用harmonyos提供的http模块实现http数据请求,接下来我们这里用第三方库来实现,如果做过前端开发的同学对于这个库应该不陌生,因为axios是前端开发中用来发送ajax请求的最流行的一个第三方库,ajax请求本质也属于http请求,因此在鸿蒙开发中也依然可以使用axios,接下来我们开始讲解如何在鸿蒙开发中使用axios。

因为axios并不是harmonyos官方提供的,所以我们并不能直接拿来就用,需要先安装ohpm,其就是鸿蒙开发中所有安装的包的一个管理工具,所以我们需要先安装它然后再利用它去安装axios,以下是ohpm的安装步骤:

ohpm安装使用教程

关于ohpm包管理工具,我们在下载DevEco Studio工具的时候,一般都已经下载好了,下面是我以前讲解该工具的安装教程,当时是装载工具的时候就已经顺便把ohpm工具下载好了:

如果你电脑没有过这个工具当然也可以重新下载,点击 下载链接 进行下载,根据自己电脑的系统配置选择不同的版本。

一般我们下载好,没有配置过环境变量是没法使用的,需要我们进行一些配置才能使用,找到我们之前下载好的工具,进入bin目录,打开该路径的cmd,输入init.bat进行初始化,然后输入如下命令可以看到ohpm的版本,但是ohpm只能在当前目录生效,并不是全局。

如果想在任意路径输入ohpm -v有效果的话,需要配置一下环境变量,如下:

接下来我们在任意路径访问ohpm都有效果了:

axios第三方库安装

接下来我们借助ohpm进行安装axios第三方库,关于harmonyos的第三方库可以参考 网站 ,里面罗列了harmonyos所有支持的第三方库的信息及其说明:

比如说我们想安装axios的话只需要找到对应的包名点击进去,里面就有详细的安装使用介绍:

复制安装命令,回到我们的编辑工具(记得要先重新一下开发者工具),找到编辑器下方菜单中的终端选项,输入如下命令进行安装:

安装完成之后我们的包就下载到 oh_modules 中,然后包的信息就存储到oh_package.json5中:

axios的使用

安装好axios包之后,接下来就开始正式使用axios,将上面的按钮编写接口的代码换成axios进行如下编写,如下:

import axios from '@ohos/axios'

class getAPI {
  // 获取猫的图片
  getCat(){
    return new Promise((resolve, reject) => {
      axios.get('https://api.thecatapi.com/v1/images/search?limit=2')
        .then((resp) => {
          if(resp.status === 200){
            // 请求成功
            resolve(resp.data)
          }else{
            console.log('查询信息失败!', JSON.stringify(resp))
            reject('查询信息失败!')
          }
        })
        .catch((err: Error) => {
          // 请求失败
          console.log('查询信息失败!', JSON.stringify(err))
          reject('查询信息失败!')
        })
    })
  }

  // 获取猫的图片
  getWord(){
    return new Promise((resolve, reject) => {
      axios.get('http://api.uomg.com/api/rand.qinghua')
        .then((resp) => {
          if(resp.status === 200){
            // 请求成功
            resolve(resp.data)
          }else{
            console.log('查询信息失败!', JSON.stringify(resp))
            reject('查询信息失败!')
          }
        })
        .catch((err: Error) => {
          // 请求失败
          console.log('查询信息失败!', JSON.stringify(err))
          reject('查询信息失败!')
        })
    })
  }
}

const getApi = new getAPI()
export default getApi

达到的效果是一致的,说明我们使用axios发送请求完全没问题,了解更多axios也可以参考文档:

数据持久化

应用在使用过程中会产生各种各样的数据,如果没有对数据进行持久化处理,一旦应用进行重启这些数据就会全部丢失,那它肯定是不符合用户使用的一个需求,所以我们必须对这些数据进行持久化处理,在harmonyos中实现数据持久化主要有以下两种常用方式:

用户首选项

用户首选项 (Preference) 为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,以下是使用用户首选项的基本流程图:

以下是 用户首选项 使用的基本步骤:

1)导入用户首选项模块:

import dataPreference from '@ohos.data.preferences'

2)获取首选项实例,读取指定文件:

dataPreference.getPreferences(this.content, 'MyAppPreferences')
  .then(preferences => {
    // 获取成功
  })
  .catch(reason => {
    // 获取失败
  })

3)数据操作:(key为string,要求非空且长度不超80字节,数据量建议不超1w条,轻量级)

// 3.1.写入数据,如果已经存在则会覆盖,可利用.has()判断是否存在
preferences.put('key', val)
  .then(() => preferences.flush()) // 刷到磁盘
  .catch(reason => J) // 处理异常
//3.2.删除数据
preferences.delete('key')
 .then(() => ).catch(reason => [])
//3.3.查询数据
preferences.get('key', 'defaultValue')
 .then(value => console.log('查询成功'))
 .catch(reason => console.log('查询失败'))

接下来对用户的首选项数据持久化进行一个简单的操作,首先我们先定义一个实例用来增删改查数据:

import preferences from '@ohos.data.preferences';

class PreferencesUtil {
  prefMap: Map<string, preferences.Preferences> = new Map()

  // 加载preferences实例
  async loadPreference(content, name: string){
    try {
      let pref = await preferences.getPreferences(content, name)
      this.prefMap.set(name, pref)
      console.log('testTag', `加载Preferences[${name}]成功`)
    }catch (e){
      console.log('testTag', `加载Preferences[${name}]失败`, JSON.stringify(e))
    }
  }
  // 新增数据
  async putPreferencesValue(name: string, key: string, value: preferences.ValueType){
    if (!this.prefMap.has(name)) {
      console.log('testTag', `Preferences[${name}]尚未初始化`)
      return
    }
    try {
      let pref = this.prefMap.get(name)
      // 写入数据
      await pref.put(key, value)
      // 刷盘
      await pref.flush()
      console.log('testTag', `保存Preferences[${name}.${key} = ${value}]成功`)
    } catch (e){
      console.log('testTag', `保存Preferences[${name}.${key} = ${value}]失败`, JSON.stringify(e))
    }
  }

  // 读取数据
  async getPreferencesValue(name: string, key: string, defaultValue: preferences.ValueType){
    if (!this.prefMap.has(name)) {
      console.log('testTag', `Preferences[${name}]尚未初始化`)
      return
    }
    try {
      let pref = this.prefMap.get(name)
      // 读取数据
      let value = await pref.get(key, defaultValue)
      console.log('testTag', `读取Preferences[${name}.${key} = ${value}]成功`)
      return value
    } catch (e){
      console.log('testTag', `读取Preferences[${name}.${key}]失败`, JSON.stringify(e))
    }
  }

  // 删除数据
  async deletePreferencesValue(name: string, key: string){
    if (!this.prefMap.has(name)) {
      console.log('testTag', `Preferences[${name}]尚未初始化`)
      return
    }
    try {
      let pref = this.prefMap.get(name)
      // 删除数据
      await pref.delete(key)
      // 刷盘
      await pref.flush()
      console.log('testTag', `删除Preferences[${name}.${key}]成功`)
    } catch (e){
      console.log('testTag', `删除Preferences[${name}.${key}]失败`, JSON.stringify(e))
    }
  }
}

const  preferencesUtil = new PreferencesUtil()
export default preferencesUtil as PreferencesUtil

在创建ability实例的文件中,在onCreate函数出进行一个调用:

在调用完成之后,我们进入到要持久化存储数据的界面,然后调用aboutToAppear函数在页面加载前读取数据,没有数据选择默认数据:

在修改数据后,对修改后的数据进行一个新增:

最后在真机中进行数据模仿,本地预览器是没有任何效果的,结果如下:

关系型数据库

关系型数据库(RDB)是基于SQLite组件提供的本地数据库,用于管理应用中的结构化数据。例如: 记账本、备忘录。以下是关系型数据库的运行流程图:

以下是 关系型数据库 使用的基本步骤:

1)导入关系型数据库模块:

import relationalStore from '@ohos.data.relationalStore';

2)初始化数据库表:

// 2.1.rdb配置
const config = {
  name: 'MyApplication.db',// 数据库文件名
  securityLevel: relationalstore.SecurityLevel.S1 // 数据库安全级别
}
// 2.2.初始化表的SQL
const sql = `CREATE TABLE IF NOT EXISTS TASK (
              ID INTEGER PRIMARY KEY AUTOINCREMENT,
              NAME TEXT NOT NULL,
              FINISHED bit
             )`
// 2.3获取rdb
relationalStore.getRdbStore(this.context, config,(err,rdbStore) => {
  // 2.4执行Sql,后续的所有增删改查都是使用rdbstore对象
  rdbStore.executeSql(sql)
})

3)增删改查的数据操作:

// 新增数据
let task = {id: 1, name: '任务', finished: false}; // 准备数据
this.rdbStore.insert(this.tableName, task) // 新增

// 修改数据
let task = {'finished': true}; // 要更新的数据
let predicates = new relationalStore.RdbPredicates(this.tableName) // 查询条件,RdbPredicates为条件谓词
predicates.equalTo('ID', id)
this.rdbStore.update(task, predicates) // 执行更新

// 删除数据
let predicates = new relationalStore.RdbPredicates(this.tableName) // 查询条件
predicates.equalTo('ID', id)
this.rdbStore.delete(predicates) // 执行删除

// 查询数据
let predicates = new relationalStore.RdbPredicates(this.tableName) // 查询条件
let result = await this.rdbStore.query(predicates, ['ID', 'NAME', 'FINISHED']) // 执行查询
let tasks: any[] = [] // 准备数组保存结果
while(!result.isAtLastRow) { // 循环遍历结果集,判断是否结果是否遍历到最后一行
  result.goToNextRow() // 指针移动到下一行数据
  // 根据字段名获取字段index,从而获取字段值
  let id = result.getLong(result.getColumnIndex('ID'))
  let name = result.getString(result.getColumnIndex('NAME'))
  tasks.push({id, name})
}

接下来对 关系型数据库 数据持久化进行一个简单的操作,首先我们先定义一个实例用来增删改查数据: 

import relationalStore from '@ohos.data.relationalStore';

class TaskModel {
  private rdbStore: relationalStore.RdbStore
  private tableName: string = 'TASK'
  // 初始化任务列表
  initTaskDB(context){
    // rdb配置
    const config = {
      name: 'MyApplication.db',
      securityLevel: relationalStore.SecurityLevel.S1 // 安全级别
    }
    // 初始化SQL语句
    const sql = `CREATE TABLE IF NOT EXISTS TASK (
              ID INTEGER PRIMARY KEY AUTOINCREMENT,
              NAME TEXT NOT NULL,
              FINISHED bit
             )`
    // 获取rdb
    relationalStore.getRdbStore(context, config, (err, rdbStore) => {
      if(err) {
        console.log('testTag', '获取rdbStore失败!')
        return
      }
      // 执行sql
      rdbStore.executeSql(sql)
      console.log('testTag', '创建task表成功!')
      // 保存rdbStore
      this.rdbStore = rdbStore
    })
  }
  // 查询任务列表
  async getTaskList() {
    // 构建查询条件
    let predicates = new relationalStore.RdbPredicates(this.tableName)
    // 查询
    let result = await this.rdbStore.query(predicates, ['ID', 'NAME', 'FINISHED'])
    // 解析查询结果
    let tasks: any[] = [] // 准备数组保存结果
    while(!result.isAtLastRow) { // 循环遍历结果集,判断是否结果是否遍历到最后一行
      result.goToNextRow() // 指针移动到下一行数据
      // 根据字段名获取字段index,从而获取字段值
      let id = result.getLong(result.getColumnIndex('ID'))
      let name = result.getString(result.getColumnIndex('NAME'))
      let finished = result.getLong(result.getColumnIndex('FINISHED'))
      tasks.push({id, name, finished})
    }
    console.log('testTag', '查询到数据:', JSON.stringify(tasks))
    return tasks
  }

  /*
   * 添加任务列表
   * @param name 任务名称
   * @returns 任务id
   * */
  addTask(name: string): Promise<number> {
    return this.rdbStore.insert(this.tableName, {name, finished: false})
  }

  /*
 * 根据id更新任务列表
 * @param id 任务id
 * @param finished 任务是否完成
 * */
  updateTaskStatus(id: number, finished: boolean) {
    // 要更新的数据
    let data = {finished}
    // 更新的条件
    let predicates = new relationalStore.RdbPredicates(this.tableName)
    predicates.equalTo('ID', id)
    // 更新操作
    return this.rdbStore.update(data, predicates)
  }

  /*
  * 根据id删除任务列表
  * @param id 任务id
  * */
  deleteTaskId(id: number, finished: boolean) {
    // 删除的条件
    let predicates = new relationalStore.RdbPredicates(this.tableName)
    predicates.equalTo('ID', id)
    // 删除操作
    return this.rdbStore.delete(predicates)
  }
}

let taskModel = new TaskModel()
export default taskModel as TaskModel

然后在页面加载的时候进行调用:

新增任务的位置进行引用:

删除的位置进行引用:

更新的位置进行引用:

最终呈现的效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1383155.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超详细的嵌入式cJSON使用注意事项,持续补充中......

文章目录 一、堆内存不足1.1 问题描述1.2 解决办法 二、内存泄露2.1 忘记Delete2.2 忘记Free2.3 串口数据接收缺少部分字符导致的内存泄露(自己的问题)问题分析 2.4 内存泄露在Cortex-M3内核会发生什么&#xff1f; cJSON开源库地址&#xff1a; cJSON 一、堆内存不足 1.1 问…

ssh 远程登录协议

一、SSH 服务 1.1 SSH 基础 SSH&#xff08;Secure Shell&#xff09;是一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程 复制等功能。SSH 协议对通信双方的数据传输进行了加密处理&#xff0c;其中包括用户登录时输入的用户口令&#xff0c;SSH 为建立在应…

mongoose6.0版以上操作mongodb数据库的基本使用

1、介绍 Mongoose 是一个对象文档模型库&#xff0c;官网 http://www.mongoosejs.net/ 2、作用 方便使用代码操作 mongodb 数据库 3、使用流程 3.1、链接数据库 //1. 安装 mongoose---> npm install mongoose --save//2. 导入 mongoose const mongoose require(&quo…

PiflowX-DorisWrite组件

DorisWrite组件 组件说明 往Doris存储写入数据。 计算引擎 flink 组件分组 doris 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许值是否必填描述例子fenodesFenodes“”无是Doris FE http地址&#xff0c; 支持多个…

PLC-IoT 网关开发札记(4):Xamarin Forms 实现自定义控件(一个开关)

1. 需求 物联网项目中要集成大量的设备&#xff0c;作为一种简单的数字孪生手段&#xff0c;每一型号的设备都需要一个对应的虚拟实现&#xff0c;也就是用界面把这个设备呈现出来。设备有多个可管理的“属性”&#xff0c;对这个设备的监测对应获取这个设备“属性”的值&…

Linux系统编程(十一):高级 IO

参考引用 UNIX 环境高级编程 (第3版)嵌入式Linux C应用编程-正点原子 Linux系统编程&#xff08;文章链接汇总&#xff09; 1. 非阻塞 I/O 阻塞就是进入了休眠状态&#xff0c;交出了 CPU 控制权阻塞 I/O 就是对文件的 I/O 操作&#xff08;读写操作&#xff09;是阻塞式的&a…

FGSM方法生成交通信号牌的对抗图像样本

背景&#xff1a; 生成对抗样本&#xff0c;即扰动图像&#xff0c;让原本是“停车”的信号牌识别为“禁止驶入” 实验准备 模型&#xff1a;找一个训练好的&#xff0c;识别交通信号牌的CNN模型&#xff0c;灰度图像 模型地址&#xff1a;GitHub - Daulettulegenov/TSR_CNN:…

高级RAG(六): 句子-窗口检索

之前我们介绍了LlamaIndex的从小到大的检索 的检索方法&#xff0c;今天我们再来介绍llamaindex的另外一种高级检索方法: 句子-窗口检索(Sentence Window Retrieval)&#xff0c;在开始介绍之前让我们先回顾一下基本的RAG检索的流程&#xff0c;如下图所示&#xff1a; 在执行基…

学会编写自定义configure脚本,轻松实现定制化配置

学会编写自定义configure脚本&#xff0c;轻松实现定制化配置 一、configure脚本的作用和重要性二、configure脚本的基本结构和语法三、编写自定义configure脚本的步骤四、示例五、常见的问题总结 一、configure脚本的作用和重要性 configure脚本是用于自动配置软件源代码的脚…

jmeter如何做接口测试?

Jmeter介绍&测试准备&#xff1a; Jmeter介绍&#xff1a;Jmeter是软件行业里面比较常用的接口、性能测试工具&#xff0c;下面介绍下如何用Jmeter做接口测试以及如何用它连接MySQL数据库。 前期准备&#xff1a;测试前&#xff0c;需要安装好Jmeter以及jdk并配置好jdk环…

高级JavaScript。同步和异步,阻塞和非阻塞

同步阻塞 同步非阻塞 异步阻塞 异步非阻塞 在当什么是同步和异步&#xff0c;阻塞与非阻塞的概念还没弄清楚之前&#xff0c;更别提上面这些组合术语了&#xff0c;只会让你更加困惑。 同步和异步 同步和异步其实指的是&#xff0c;请求发起方对消息结果的获取是主动发起…

强化学习应用(五):基于Q-learning算法的无人车配送路径规划(通过Python代码)

一、Q-learning算法介绍 Q-learning是一种强化学习算法&#xff0c;用于解决基于环境的决策问题。它通过学习一个Q-table来指导智能体在不同状态下采取最优动作。下面是Q-learning算法的基本步骤&#xff1a; 1. 定义环境&#xff1a;确定问题的状态和动作空间&#xff0c;并…

NI PXIe-6386国产替代,8路AI(16位,14 MS/s/ch),2路A​O,24路DIO,PXI多功能I/O模块

PXIe-6386 PXIe&#xff0c;8路AI&#xff08;16位&#xff0c;14 MS/s/ch&#xff09;&#xff0c;2路A​O&#xff0c;24路DIO&#xff0c;PXI多功能I/O模块 PXIe-6386是一款同步采样的多功能DAQ设备。该模块提供了模拟 I/O、数字I/O、四个32位计数器和模拟和数字触发。板载N…

2024年【G1工业锅炉司炉】考试及G1工业锅炉司炉考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 G1工业锅炉司炉考试根据新G1工业锅炉司炉考试大纲要求&#xff0c;安全生产模拟考试一点通将G1工业锅炉司炉模拟考试试题进行汇编&#xff0c;组成一套G1工业锅炉司炉全真模拟考试试题&#xff0c;学员可通过G1工业锅…

【现代密码学】笔记3.1-3.3 --规约证明、伪随机性《introduction to modern cryphtography》

【现代密码学】笔记3.1-3.3 --规约证明、伪随机性《introduction to modern cryphtography》 写在最前面私钥加密与伪随机性 第一部分密码学的计算方法论计算安全加密的定义&#xff1a;对称加密算法 伪随机性伪随机生成器&#xff08;PRG&#xff09; 规约法规约证明 构造安全…

LeetCode刷题.15(哈希表与计数排序解决41. 缺失的第一个正数)

给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 示例 2&#xff1a; 输入&#xff1a;nums …

MCS-51---串行通信的特点

目录 一.同步通信和异步通信 1.异步通信 2.同步通信 二.串行通信的方式 1.单工 2.半双工 3.全双工 三.串行通信的速率 四.MCS-51单片机结构 五.串行口的控制 1.串行口控制寄存器(SCON) 2.电源控制寄存器(PCON) 六.波特率的设计 七.串行口的工作方式 1.方式0 2.…

NLP论文阅读记录 - WOS | ROUGE-SEM:使用ROUGE结合语义更好地评估摘要

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结 前言 ROUGE-SEM: Better evaluation of summarization using ROUGE combin…

操作系统详解(5.1)——信号(Signal)的相关题目

系列文章&#xff1a; 操作系统详解(1)——操作系统的作用 操作系统详解(2)——异常处理(Exception) 操作系统详解(3)——进程、并发和并行 操作系统详解(4)——进程控制(fork, waitpid, sleep, execve) 操作系统详解(5)——信号(Signal) 文章目录 题目第一问第二问第三问 题目…

python24.1.14while循环

当条件结束时间未知时&#xff0c;while循环比for循环更合适 实践