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

【Qt-数据库】

Qt编程指南

  • ■ SQLite
  • ■ CSV
  • ■ JSON

■ SQLite

Qt 提供了很多操作数据库的类,
SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于 250KiB。 SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。就像其他数据库, SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。 SQLite 可以直接访问其存储文件。

QSqlDatabase 类用于建立数据库的连接,往往以指定加载的数据库驱动,然后设置数据库的登录参数,如主机地址,用户名、登录密码等。这些都是服务器类型的数据库所需要做的操作
在 QSqlDatabase 连接数据库后,用 QSqlTableModel 从数据库里读取出表格模型,然后通过 Qt 的 QTableView 类显示数据库的内容在我们面前。

/*需要添加模块*/
QT       += sql/* 查看本机可用的数据库驱动 */
QStringList drivers = QSqlDatabase::drivers();
foreach(QString driver, drivers) {qDebug()<<driver;
}/* 以QSQLITE驱动方式打开或者创建数据库 */
sqlDatabase = QSqlDatabase::addDatabase("QSQLITE");
sqlDatabase.setDatabaseName("alarm.db");
/* 以open的方式打开alarm.db数据库,则会创建一个alarm.db */
if (!sqlDatabase.open())qDebug()<<"连接数据库错误"<<sqlDatabase.lastError()<<endl;
elseqDebug()<<"连接数据库成功"<<endl;QSqlQuery query(sqlDatabase);/* 使用指令式创建表 */
query.exec("create table alarm (id int primary key, time vchar(15), flag vchar(5))");  // primary 说明id不能为空
/* 以指令的方式插入数据 */
//query.exec("insert into alarm values(0, '06:00', 'false')");model = new QSqlTableModel(this, sqlDatabase);
/* 模型设置表的名字,需要与数据库的表的名字相同 */
model->setTable("alarm");/* 如果有修改则同步修改到数据库,* 注意这个规则需要与tabview这样的控件才生效,* 因为tabview可以直接编辑表里的内容 */
model->setEditStrategy(QSqlTableModel::OnFieldChange);
/* 成功则返回true,查看数据库里是否有alarm这个表格 */
model->select();/* 如果数据表数据为空,则添加两个闹钟 */
if (model->rowCount() == 0) {/* 插入一行 */model->insertRow(model->rowCount());/* 在该行插入数据 */model->setData(model->index(0, 0), 1);model->setData(model->index(0, 1), "06:00");model->setData(model->index(0, 2), "false");/* 插入数据后记得提交 */model->submit();/* 再插入一行 */model->insertRow(model->rowCount());model->setData(model->index(1, 0), 2);model->setData(model->index(1, 1), "18:00");model->setData(model->index(1, 2), "true");/* 提交 */model->submit();
}/* 打印出闹钟数据库里的信息 */
for (int i = 0; i < model->rowCount(); i++) {for (int j = 0; j < 3; j++) {QModelIndex qindex = model->index(i, j);switch (j) {case 0:qDebug()<<"第"<< model->data(qindex).toInt()<<"行数据";break;case 1:listWidget->addItem(model->data(qindex).toString());qDebug()<<"闹钟时间为:"<< model->data(qindex).toString();break;case 2:qDebug()<<"闹钟状态为:" << model->data(qindex).toString()<<endl;if (model->data(qindex).toString() != "true")listWidget->item(i)->setTextColor(QColor(22, 22, 22, 60));elselistWidget->item(i)->setTextColor(QColor(22, 22, 22, 225));break;default:break;}}
}/* 获取数据库里的闹钟开关状态 */
QModelIndex qindex = model->index(i, 2);
bool sw = model->data(qindex).toBool()/*设置数据库里的闹钟开关状态 */
QModelIndex qindex = model->index(i, 2);
model->setData(qindex, "true");

■ CSV

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),

■ JSON

QJsonValue
void remove(const QString &key);
QJsonValue take(const QString &key);
bool contains(const QString &key) const;
void remove(QStringView key);
void remove(QLatin1String key);
QJsonValue take(QStringView key);
QJsonValue take(QLatin1String key);
bool contains(QStringView key) const;
bool contains(QLatin1String key) const;QJsonArray
删除数组 i;
void removeAt(int i);   //jArray.removeAt(0);  //ok //删除第0项
QJsonValue takeAt(int i);  //qDebug() << jArray.takeAt(0).toInt() << endl;      //删除第0项并返回值
替换:
QJsonArray jArray= configJson->RootObj().value("IP").toArray();
jArray.insert(3,jArray);  //ok
jArray.replace(3,jArray); //ok
jArray[4]= 12;            //无效   数组越界无效
jArray[0]= 54;            //ok  
(*configJson->RootObjPointer())["IP"]=jArray;      //获取指针方式修改“IP”
configJson->savejsonfile();
QJsonObject
是否包含 
是否包含Student
QJsonObject obj=doc.object();
if(obj.contains("Student"))
{
}/*创建对象并转换成QByteArray*/
QJsonObject rootobj;
rootobj["sn"] = 20001;
rootobj["type"] = "hub";
QJsonDocument jsonDoc(rootobj);
QByteArray byte=jsonDoc.toJson(); //按照json风格生成字符串,自动缩进,有空格和\n \t ; 数据量大
QByteArray byte=jsonDoc.toJson(QJsonDocument::Compact);//传入参数获取压缩后的序列化结果,紧凑格式,直接生成一堆字符串,但是占用控件小/*QByteArray转换成QJsonDocument,并得到数据*/
QJsonDocument jsonDoc1 = QJsonDocument::fromJson(byte); //QByteArray转换成文档对象
QJsonObject obj1 = jsonDoc1.object();
qDebug() << "obj1=" << obj1["sn"].toInt() <<  obj1["type"].toString() << endl;插入
jsonObject.insert("name", QString::number(i+1));
jsonObject.insert("age", i+18);
jsonObject.insert("time", QDateTime::currentDateTime().toString());json说明
/*【】是用来填充数据使用 */
(*configJson->RootObjPointer())["IP"]=jArray;
/*.value 这种方式是用来获取数据*/
(*configJson->RootObjPointer()).value("IP")=jArray;json注意事项:
数组中不能是00    "NightMode": [18, 00, 0, 6, 0, 0]   //解析不出来
数组中是int类型的数据 不要用QString 去替换,会不成功。
修改json类型要修改他的指针,重新填充数据要重新赋值给上层的父类,保存才能达到效果,不能获取的只是临时变量。(如下例子)QJsonArray jArray= configJson->RootObj().value("IP").toArray();
jArray[4]= 12;            //无效  (数组越界 )
jArray.insert(3,jArray);  //ok   (可以插入任意类型 )
jArray.replace(3,jArray); //ok   (可以替换任意类型 )
jArray[0]= 54;            //ok  (数组不越界 )
(*configJson->RootObjPointer())["IP"]=jArray;  //Ok      (通过指针来获取“IP”,并赋值)
configJson->savejsonfile();案例1:
QString fileName = QCoreApplication::applicationDirPath();
fileName+="/pdoctor.json";
doctorjson = new Json(fileName);
QJsonArray doctor = doctorjson->Obj()["data"].toArray();
int row = doctor.count();
for (int i=0;i<row;i++)
{
}
doctor.at(i).toObject()["advice"].toObject()["adviceSeq"].toInt();
doctor.at(i).toObject()["advice"].toObject()["drugName"].toString();
doctor.at(i).toObject()["advice"].toObject()["adviceType"].toInt();
doctor.at(i).toObject()["advice"].toObject()["freq"].toString();
doctor.at(i).toObject()["advice"].toObject()["drugvolume"].toDouble();
doctor.at(i).toObject()["advice"].toObject()["drugDensity"].toDouble();案例2:
案例3/*****************************************************************************************/
QByteArray byte;
QFile file(file_path);
if(file.exists()){file.open(QIODevice::ReadOnly|QIODevice::Text);byte=file.readAll();file.close();
}    
else
{cout<<"openFileError"<<endl;;
}
QJsonParseError json_error;
QJsonDocument jsonDoc(QJsondocument::fromJson(byte,&json_error));
if(json_error.err!=QJsonParseError::NoError)
{cout<<" json error "<<endl;
}
QJsonObject rootobj=jsonDoc.object();
//一般需要使用 rootobj.contains(xxx) 判断一下是否存在 这里我们就默认是存在的 。QJsonObject A_obj=rootobj.value("A").toObject();
A_obj["AA"]=33;QJsonArray B_array=rootobj.value("B").toArray();
QJsonObject B_Subobj=B_array[0].toObject();
QJsonArray b_array=B_Subobj.value("BB").toArray();
b_array.replace(0,"BBB");
B_Subobj["BB"]=b_array;
B_array.replace(0,B_Subobj);QJsonObject C_obj=rootobj.value("C").toObject();
QJsonArray c_array=C_obj.value("CC").toArray();
c_array.replace(0,"CCC");
C_obj["CC"]=c_array;rootobj["A"]=A_obj;
rootobj["B"]=B_array;
rootobj["C"]=C_obj;QFile file(file_path);
if(file.exists()){file.open(QIODevice::WriteOnly|QIODevice::Text);jsonDoc.setObject(rootobj);file.seek(0);file.write(jsonDoc.toJson());file.flush();file.close();
}dock案例:
#include "json.h"
Json::Json(QString fileName)
{jsonName=fileName;openjsonfile(jsonName);
}Json::~Json()
{savejsonfile();
}void Json::openjsonfile(QString name)
{if(QFile::exists(name)){QByteArray      byte;QJsonDocument   jsonDoc;QFile           file;file.setFileName(name);file.open(QFile::ReadOnly|QIODevice::Text);byte= file.readAll();jsonDoc = QJsonDocument::fromJson(byte);//转换成文档对象if(jsonDoc.isObject()){      //判断文档对象中存储的数据是不是json对象isfile = true;rootobj = jsonDoc.object();//得到rootJson对象file.close();}}else{isfile = false;}
}
void Json::savejsonfile()
{QFile           file;QJsonDocument jsonDoc(rootobj);     //将Json对象,转换成Json文档
//  jsonDoc.setObject(rootobj);file.setFileName(jsonName);file.open(QFile::WriteOnly|QIODevice::Text);file.seek(0);file.write(jsonDoc.toJson());file.flush();file.close();
}int Json::getKeyIntVal(QString key)
{return rootobj[key].toInt();
}QString Json::getKeyStringVal(QString key)
{return rootobj[key].toString();
}bool Json::getKeyBoolVal(QString key)
{return rootobj[key].toBool();
}//读取空值(因其没有对应的to类型函数,可使用下方类型接收或isNull()函数判断)
QVariant Json::getKeyVarialVal(QString key)
{return rootobj[key].toVariant();
}QJsonObject Json::getKeyQJsonObject(QString key)
{return rootobj[key].toObject();
}QJsonArray Json::getKeyQJsonArray(QString key)
{return rootobj[key].toArray();
}int Json::getArrayIndexIntVal(QString key, int index)
{return rootobj[key].toArray().at(index).toInt();
}QJsonObject Json::RootObj()
{return rootobj;
}QJsonObject* Json::RootObjPointer()
{return &rootobj;
}bool Json::getisfile()
{return isfile;
}void Json::insertKeyIntVal(QString key, int valu)
{rootobj[key]=valu;
}/*
*
*netjson->insertKeyBoolVal("NightMode",true);  ok
*/
void Json::insertKeyBoolVal(QString key, bool valu)
{rootobj[key]=valu;
}/*
*netjson->insertKeyStringVal("NightMode","opopopo"); Ok
*/
void Json::insertKeyStringVal(QString key, QString valu)
{rootobj[key]=valu;
}/*
*   QJsonArray c_JsArr;
*   c_JsArr.append(12);
*   c_JsArr.append(32);
*   netjson->insertKeyArrayVal("NightMode",c_JsArr); //Ok
*/
void Json::insertKeyArrayVal(QString key, QJsonArray array)
{rootobj[key]= array;
}/*
*   QJsonObject jsobject;jsobject["opo"] = "qqqqqq";jsobject["op1"] = 12;jsobject["op2"] = true;jsobject["op3"] = "rrrrrr";netjson->insertKeyObjectVal("NightMode",jsobject);
*
*/
void Json::insertKeyObjectVal(QString key, QJsonObject jsobject)
{rootobj[key]=jsobject;
}/*
* netjson->replaceKeyArrayIndexVal("NightMode",5,10); //ok
**/
void Json::replaceKeyArrayIndexVal(QString key, int index, int valu)   //valu  为 QString 不能替换
{QJsonArray c_JsArr = rootobj.value(key).toArray();c_JsArr.replace(index,valu);rootobj[key]=c_JsArr;
}/*  数组里面添加QJsonArray
*   QJsonArray c_JsArr;
*   c_JsArr.append(12);
*   c_JsArr.append(32);
*   c_JsArr.replace(0,24); //替换
*   netjson->insertArrayKeyAddArrayVal("NightMode",0,c_JsArr);
*/void Json::insertArrayKeyAddArrayVal(QString key, int index, QJsonArray valu)
{QJsonArray c_JsArr = rootobj.value(key).toArray();c_JsArr[index] = valu;rootobj[key]=c_JsArr;
}/*
* 数组里面添加QJsonObject
*   QJsonObject jsobject;
*   jsobject["opo"] = "qqqqqq";
*   jsobject["op1"] = 12;
*   jsobject["op2"] = true;
*   jsobject["op3"] = "rrrrrr";
*   netjson->insertArrayKeyAddObjectVal("NightMode",0,jsobject);
*/
void Json::insertArrayKeyAddObjectVal(QString key, int index, QJsonObject jsobject)
{QJsonArray c_JsArr = rootobj.value(key).toArray();c_JsArr[index] = jsobject;rootobj[key]=c_JsArr;
}#ifndef JSON_H
#define JSON_H#include <QtWidgets/QWidget>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonValue>
#include <QDebug>
#include <QString>
#include <QByteArray>
#include <QFile>class Json
{
public:Json(QString file);~Json();void openjsonfile(QString name);void savejsonfile();int getKeyIntVal(QString key);QString getKeyStringVal(QString key);bool getKeyBoolVal(QString key);QVariant getKeyVarialVal(QString key);QJsonArray  getKeyQJsonArray(QString key);QJsonObject getKeyQJsonObject(QString key);int getArrayIndexIntVal(QString key, int index);QJsonObject RootObj();QJsonObject* RootObjPointer();bool getisfile();//将键值对添加到Json对象中void insertKeyIntVal(QString key,int valu);void insertKeyBoolVal(QString key,bool valu);void insertKeyStringVal(QString key,QString valu);void insertKeyArrayVal(QString key,QJsonArray array);void insertKeyObjectVal(QString key, QJsonObject jsobject);void replaceKeyArrayIndexVal(QString key, int index, int valu);void insertArrayKeyAddArrayVal(QString key, int index, QJsonArray valu);void insertArrayKeyAddObjectVal(QString key, int index, QJsonObject jsobject);
private:QString         jsonName;QJsonObject     rootobj;bool            isfile ;
};#endif // JSON_H

相关文章:

【Qt-数据库】

Qt编程指南 ■ SQLite■ CSV■ JSON ■ SQLite Qt 提供了很多操作数据库的类&#xff0c; SQLite 是非常小的&#xff0c;是轻量级的&#xff0c;完全配置时小于 400KiB&#xff0c;省略可选功能配置时小于 250KiB。 SQLite 是一个进程内的库&#xff0c;实现了自给自足的、无…...

windows文件名命名规范(文件名规范、命名规则、避免特殊字符、注意文件名长度限制260个字符)

文章目录 Windows文件名命名规范1. 基本规则1.1 避免使用特殊字符1.2 限制文件名长度1.3 避免使用预留名称 2. 最佳实践2.1 使用描述性名称2.2 使用连字符或下划线代替空格2.3 使用日期和版本号 3. 实用技巧3.1 批量重命名文件3.2 使用PowerShell进行高级文件操作 Windows文件名…...

如何修改MySQL的默认端口

MySQL是世界上最流行的开源关系型数据库管理系统之一。在某些情况下&#xff0c;由于安全性、网络策略或端口冲突的原因&#xff0c;数据库管理员可能需要更改MySQL服务的默认监听端口。本文将指导您如何在不同的操作系统上更改MySQL的默认端口。 理解MySQL配置文件 MySQL的配…...

Android笔记(二十一):Room组件实现Android应用的持久化处理

一、Room组件概述 Room是Android JetPack架构组件之一&#xff0c;是一个持久处理的库。Room提供了在SQLite数据库上提供抽象层&#xff0c;使之实现数据访问。 &#xff08;1&#xff09;实体类&#xff08;Entity&#xff09;&#xff1a;映射并封装了数据库对应的数据表中…...

uniapp中各种状态的按钮

当涉及状态按钮时&#xff0c;UniApp提供了丰富的选择。UniApp中的状态按钮可以是开关按钮、单选按钮、多选按钮等。开发者可以根据具体需求选择使用合适的状态按钮组件。对于状态按钮&#xff0c;UniApp提供了丰富的API和事件&#xff0c;可以轻松实现状态切换、状态监听等功能…...

模式识别与机器学习-判别式分类器

模式识别与机器学习-判别式分类器 生成式模型和判别式模型的区别线性判别函数多分类情况多分类情况1多分类情况2多分类情况3 例题 广义线性判别函数实例 分段线性判别函数Fisher线性判别感知机算法例&#xff1a;感知机多类别分类 谨以此博客作为学习期间的记录 生成式模型和判…...

c++11 标准模板(STL)(std::pair)(七)访问 pair 的一个元素

定义于头文件 <utility> std::pair 是一个结构体模板&#xff0c;其可于一个单元存储两个相异对象。 pair 是 std::tuple 的拥有两个元素的特殊情况。 访问 pair 的一个元素 std::get(std::pair) template< size_t I, class T1, class T2 > typename std::tuple…...

IP 地址归属地查询

IP 地址归属地查询 1. IP 地址归属地查询2. IP 地址归属地查询References 1. IP 地址归属地查询 https://tool.lu/ip/index.html 2. IP 地址归属地查询 https://www.ip.cn/ip/.html References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/...

实战经验分享:在Java中灵活应用Excel注释和批注

本文由葡萄城技术团队原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 注释及批注是 Excel 中比较常用的功能&#xff0c;注释往往针对单元格&#xff0c;起到解释说明的作用&a…...

AUTOSAR从入门到精通-车载以太网(三)

目录 前言 原理 车载以太网总体架构 物理层 数据链路层 以太网帧格式<...

【自然语言处理】用Python从文本中删除个人信息-第二部分

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…...

设计模式之-中介者模式,快速掌握中介者模式,通俗易懂的讲解中介者模式以及它的使用场景

系列文章目录 设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列 设计模式之-单列设计模式&#xff0c;5种单例设计模式使用场景以及它们的优缺点 设计模式之-3种常见的工厂模式简单工厂模式、工厂方法模式和抽象工厂模式&#xff0c;每一种模式的概念、使用…...

12.25

led.c #include "led.h" void all_led_init() {RCC_GPIO | (0X3<<4);//时钟使能GPIOE_MODER &(~(0X3<<20));//设置PE10输出GPIOE_MODER | (0X1<<20);//设置PE10为推挽输出GPIOE_OTYPER &(~(0x1<<10));//PE10为低速输出GPIOE_OSPEED…...

MySQL5.7的几种安装方式总结(排错踩坑呕心沥血的经历)

包安装 添加国内源&#xff1a;mysql | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 注意&#xff1a;5.7安装之后有一个临时密码&#xff0c;进行登录并修改新密码后才可以对mysql进行操作。 可以yun list看看各个系统光盘自带的都是什么版本&…...

zookeeper基本使用

目录 环境搭建 单机版搭建 集群版搭建 基本语法使用 可视化客户端 数据结构 节点分类 1. 持久节点 2. 临时节点 3. 有序节点 4. 容器节点 5. TTL节点 节点状态 监听机制 watch监听 永久性watch 应用场景 1. 实现分布式锁 2. 乐观锁更新数据 应用场景总结 选…...

【华为机试】2023年真题B卷(python)-分月饼

一、题目 题目描述&#xff1a; 中秋节公司分月饼&#xff0c;m个员工&#xff0c;买了n个月饼&#xff0c;m<n&#xff0c;每个员工至少分1个月饼&#xff0c;但可以分多个&#xff0c;单人份到最多月饼的个数为Max1&#xff0c;单人分到第二多月饼的个数是Max2&#xff0c…...

EtherCAT主站SOEM -- 11 -- EtherCAT从站 XML 文件解析

EtherCAT主站SOEM -- 11 -- EtherCAT从站 XML 文件解析 1 EtherCAT 从站信息规范1.1 XML 文件说明1.1.1 XML 数据类型1.1.2 EtherCATInfo1.1.3 Groups1.1.4 Devices1.1.5 Modules1.1.6 Types1.1.6.1 AccessType 的组成1.1.6.2 ArraylnfoType 的组成1.1.6.3 DeviceType 的组成1.…...

YOLOv5算法改进(23)— 更换主干网络GhostNet + 添加CA注意力机制 + 引入GhostConv

前言:Hello大家好,我是小哥谈。本节课就让我们结合论文来对YOLOv5进行组合改进(更换主干网络GhostNet + 添加CA注意力机制 + 引入GhostConv),希望同学们学完本节课可以有所启迪,并且后期可以自行进行YOLOv5算法的改进!🌈 前期回顾: YOLOv5算法改进(1)— 如何去…...

centos系统部署rancher1.6版本并部署服务

1. centos上部署docker. 请参考 博客 2. 用docker安装rancher1.6 sudo docker run -d -v /mnt/rancher/db:/var/lib/mysql --restartunless-stopped -p 8080:8080 rancher/server3.浏览器登录做设置 3.1 浏览器打开 1.117.92.32:8080 #直接就登录了 3.2 第一次进入&am…...

Matlab实时读取串口数据并实时画图方法

** Matlab实时读取串口数据并实时画图方法 ** 按照数据串口协议如&#xff1a;$KT2,1.80,88.18,39.54,42.86,LO[0.72,-1.04,0.35]&#xff0c;举例。 s serialport("COM12",115200,"Timeout",5); poszeros(100000,3); j1; data1 read(s,1,"uint8&…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...