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

【protobuf】二、proto3语法详解①

文章目录

  • 前言
  • Ⅰ. 字段规则
  • Ⅱ. 消息类型的定义和使用
    • 1、定义
    • 2、使用
      • 1️⃣消息类型可作为字段类型使⽤
      • 2️⃣可导入其他 .proto 文件的消息并使用 -- import
    • 3、创建通讯录 2.0 版本的 .proto 文件
    • 4、通讯录 2.0 版本的读写实现 -- 第一种验证方式
    • 5、decode选项 -- 第二种验证方式

在这里插入图片描述

前言

​ 在语法详解部分,依旧使用 项目推进 的方式完成教学。这个部分会对通讯录进行多次升级,使用 2.x 表示升级的版本,最终将会升级如下内容:

  • 不再打印联系人的序列化结果,而是将通讯录序列化后并写入文件中。
  • 从文件中将通讯录解析出来,并进行打印。
  • 新增联系人属性,共包括:姓名、年龄、电话信息、地址、其他联系⽅式、备注。

Ⅰ. 字段规则

消息的字段可以用下面几种规则来修饰:

  • singular:消息中可以包含该字段 零次或一次。 在 proto3 语法中,字段默认使用该规则

  • repeated:消息中可以包含该字段 任意多次(包括零次),其中重复值的顺序会被保留。可以理解为定义了一个数组

​ 下面我们更新之前写的 contacts.proto 文件,在 PeopleInfo 消息类中新增 Phone 类型的字段并且将其设置为 repeated 规则,表示一个联系人有多个号码,写法如下:

syntax = "proto3";
package contacts1;// 定义电话号码信息
message Phone {string number = 1; // 不同信息类的字段编号是可以相同的
}message PeopleInfo {string name = 1;int32 age = 2;repeated Phone phone = 3; // 设置为repeated规则,表示可以有多个电话号码
}

Ⅱ. 消息类型的定义和使用

1、定义

​ 在 单个 .proto 文件中可以定义多个消息体,且 支持定义任意多层的「嵌套」类型消息体

​ 并且每个消息体中的字段编号可以重复。

syntax = "proto3";
package contacts1;// -------------------------- 1. 嵌套写法 -------------------------
message PeopleInfo {string name = 1;int32 age = 2;message Phone {string number = 1; // 不同信息类的字段编号是可以相同的}
}// -------------------------- 2. ⾮嵌套写法 -------------------------
message Phone {string number = 1; // 不同信息类的字段编号是可以相同的
}message PeopleInfo {string name = 1;int32 age = 2;
}

2、使用

1️⃣消息类型可作为字段类型使⽤

syntax = "proto3";
package contacts1;// -------------------------- 1. 嵌套写法 -------------------------
message PeopleInfo {string name = 1;int32 age = 2;message Phone {string number = 1;}repeated Phone phone = 3; // 在PeopleInfo需要注意编号
}// -------------------------- 2. ⾮嵌套写法 -------------------------
message Phone {string number = 1; 
}
message PeopleInfo {string name = 1;int32 age = 2;repeated Phone phone = 3; // 在PeopleInfo需要注意编号
}

2️⃣可导入其他 .proto 文件的消息并使用 – import

​ 通常情况下,使用 import 关键字在一个 .proto 文件中引入另一个 .proto 文件,这样可以将消息类型分割为多个文件,使代码更加模块化和可维护。

​ 下面是注意事项:

  • 若要导入的消息在其文件中 声明了命名空间,则在使用该消息时候需要使用 命名空间.消息类型 格式进行定义使用。
  • proto3 文件中可以导入 proto2 消息类型并使用它们,反之亦然。

​ 假设现在 Phone 消息类是定义在别的 proto 文件中,如下面的 phone.proto 文件:

syntax = "proto3";
package phone;message Phone {string number = 1; 
}

​ 然后我们在 contacts.proto 中的 PeopleInfo 使用 Phone 消息类:

syntax = "proto3";
package contacts1;import "phone.proto"; // 引入Phone文件message PeopleInfo {string name = 1;int32 age = 2;// 若引入的⽂件声明了package,则在使⽤该消息类时,需要⽤ “命名空间.消息类型” 格式定义repeated phone.Phone phone = 3; 
}

3、创建通讯录 2.0 版本的 .proto 文件

​ 下面我们先来完成「前言」中提到的前两个要求,也就是结合文件操作实现通讯录的读写、序列化和反序列化操作,其中我们定义第三个要求中的姓名、年龄、电话号码字段,其它的字段得等我们后面讲「特殊类型」才能进行定义!

​ 所以通讯录 2.x 的需求是向文件中写入通讯录列表,以上我们只是定义了一个联系人的消息,并不能存放通讯录列表,所以还需要再完善一下 contacts.proto

syntax = "proto3";
package contacts2;// 联系人
message PeopleInfo {string name = 1; // 姓名int32 age = 2;	 // 年龄message Phone {string number = 1; // 电话号码}repeated Phone phone = 3; 
}// 通讯录
message Contacts {repeated PeopleInfo people = 1;
}

​ 通过我们前面学的编译语法进行编译:

protoc --cpp_out=. contacts.proto

​ 编译之后就能得到 contacts.pb.h 以及 contacts.pb.cc 文件,我们打开 contacts.pb.h 文件可以看到三个很眼熟的类:

在这里插入图片描述

​ 没错,它们就是我们在 proto 中的消息体,protobuf 会自动将它们转化为对应语言的类!

​ 然后我们再观察一下三个类内一些常用的接口:

// 新增了 PeopleInfo_Phone 类
class PeopleInfo_Phone final : public ::PROTOBUF_NAMESPACE_ID::Message 
{
public:using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;void CopyFrom(const PeopleInfo_Phone& from);using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;void MergeFrom( const PeopleInfo_Phone& from) {PeopleInfo_Phone::MergeImpl(*this, from);}static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {return "PeopleInfo.Phone";}// string number = 1;void clear_number();const std::string& number() const;template <typename ArgT0 = const std::string&, typename... ArgT>void set_number(ArgT0&& arg0, ArgT... args);std::string* mutable_number();PROTOBUF_NODISCARD std::string* release_number();void set_allocated_number(std::string* number);
};// 更新了 PeopleInfo 类
class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message {
public:using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;void CopyFrom(const PeopleInfo& from);using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;void MergeFrom( const PeopleInfo& from) {PeopleInfo::MergeImpl(*this, from);}static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {return "PeopleInfo";}typedef PeopleInfo_Phone Phone;// repeated .PeopleInfo.Phone phone = 3;int phone_size() const;void clear_phone();::PeopleInfo_Phone* mutable_phone(int index);::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PeopleInfo_Phone >*mutable_phone();const ::PeopleInfo_Phone& phone(int index) const;::PeopleInfo_Phone* add_phone();const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PeopleInfo_Phone >&phone() const;};// 新增了 Contacts 类
class Contacts final : public ::PROTOBUF_NAMESPACE_ID::Message {
public:using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;void CopyFrom(const Contacts& from);using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;void MergeFrom( const Contacts& from) {Contacts::MergeImpl(*this, from);}static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {return "Contacts";}// repeated .PeopleInfo people = 1;int people_size() const;void clear_people();::PeopleInfo* mutable_people(int index);::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PeopleInfo >* mutable_people();const ::PeopleInfo& people(int index) const;::PeopleInfo* add_people();const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PeopleInfo >& people() const;

从上述的例子中可以看到:

  • 每个字段都有一个 clear_ 方法,可以将字段重新设置回 empty 状态。
  • 每个字段都有设置和获取的方法, 获取方法的方法名称与小写字段名称完全相同。但如果是消息类型的字段,其设置方法为 mutable_ 方法,返回值为消息类型的指针,这类方法会为我们开辟好空间,可以直接对这块空间的内容进行修改。
  • 对于使用 repeated 修饰的字段,也就是数组类型protobuf 为我们提供了 add_ 方法来新增一个值,并且提供了 _size 方法来查看数组存放元素的个数

4、通讯录 2.0 版本的读写实现 – 第一种验证方式

下面我们通过实现以下需求,来学习对这些头文件中函数的使用:

  1. 不再打印联系人的序列化结果,而是将通讯录序列化后并写入文件中
  2. 从文件中将通讯录解析出来,并进行打印

​ 首先是 write.cc 文件,来实现第一个需求,首先就是要读取已有的通讯录,然后再添加联系人,最后写入文件中,这用到 fstream 对象来操作比较方便,细节都在下面代码注释中

// write.cc
#include "contacts.pb.h"
#include <iostream>
#include <fstream>
using namespace std;void addPeople(::contacts2::PeopleInfo* people)
{cout << "-------------新增联系⼈-------------" << endl;cout << "请输⼊联系⼈姓名: ";string name;getline(cin, name);people->set_name(name);cout << "请输⼊联系⼈年龄:";int age;cin >> age;people->set_age(age);cin.ignore(256, '\n'); // 去除缓冲区中的回车(而上面的getline则不需要,因为getline会清除缓冲区的回车)for(int i = 1; ; i++){cout << "请输入联系人电话" << i << "(只输入回车则退出):";string number;getline(cin, number);if(number.empty())break;auto phone = people->add_phone();phone->set_number(number);}cout << "-----------添加联系⼈成功-----------" << endl;
}int main()
{contacts2::Contacts contacts;// 1. 读取本地已存在的通讯录fstream input("./contacts.bin", ios::in | ios::binary); // protobuf是二进制操作if(!input.is_open())cout << "contacts.bin not found, create new file!" << endl;else if(!contacts.ParseFromIstream(&input)){// 这个操作建议学起来!// 直接通过ParseFromIstream()获取文件流进行反序列化,还能判断是否成功,一步到位!cerr << "parse contacts.bin error!" << endl;input.close();return -1;}   input.close();// 2. 向通讯录中添加一个联系人addPeople(contacts.add_people());// 3. 将通讯录写入本地文件中fstream output("./contacts.bin", ios::out | ios::binary | ios::trunc); // 记得要覆盖写if(!contacts.SerializeToOstream(&output)){// 上面的操作,这里同理!cerr << "write contacts.bin error!" << endl;output.close();return -1;}cout << "write success" << endl;output.close();return 0;
}// makefile文件:
write:write.cc contacts.pb.ccg++ -o $@ $^ -std=c++11 -lprotobuf.PHONY:clean
clean:rm -f write

在这里插入图片描述

​ 这里介绍一个 hexdump 工具,可以将 .bin 文件中的二进制数据转化为十六进制和 ASCII 码方便我们观察,命令如下所示:

hexdump -C 二进制文件

在这里插入图片描述

​ 然后就是 read.cc 文件,负责获取通讯录序列化之后打印出各个联系人的信息:

// read.cc
#include "contacts.pb.h"
#include <iostream>
#include <fstream>
using namespace std;void printContacts(contacts2::Contacts& contacts)
{for(int i = 0; i < contacts.people_size(); ++i){cout << "------------联系⼈" << i + 1 << "------------" << endl;cout << "名称:" << contacts.people(i).name() << endl;cout << "年龄:" << contacts.people(i).age() << endl;for(int j = 0 ; j < contacts.people(i).phone_size(); ++j)cout << "手机号码" << j + 1 << ":" << contacts.people(i).phone(j).number() << endl;cout << "------------------------------" << endl;}
}int main()
{contacts2::Contacts contacts;// 1. 读取本地已存在的通讯录(默认存在,故不需要判断是否存在)fstream input("./contacts.bin", ios::in | ios::binary); // protobuf是二进制操作if(!contacts.ParseFromIstream(&input)){// 这个操作建议学起来!// 直接通过ParseFromIstream()获取文件流进行反序列化,还能判断是否成功,一步到位!cerr << "parse contacts.bin error!" << endl;input.close();return -1;}   input.close();// 2. 打印通讯录列表printContacts(contacts);return 0;
}

在这里插入图片描述

5、decode选项 – 第二种验证方式

​ 其实我们可以不用像上面那么麻烦专门写个程序查看当前序列化的内容,可以直接使用 protoc -h 命令来查看 ProtoBuf 为我们提供的所有命令选项。

​ 其中 ProtoBuf 提供一个 命令选项 --decode ,表示从标准输入中读取给定类型的二进制消息,并将其以文本格式写入标准输出。 注意消息类型必须在 .proto 文件或导入的文件中定义!

在这里插入图片描述
在这里插入图片描述

​ 非常方便是吧!
在这里插入图片描述

相关文章:

【protobuf】二、proto3语法详解①

文章目录 前言Ⅰ. 字段规则Ⅱ. 消息类型的定义和使用1、定义2、使用1️⃣消息类型可作为字段类型使⽤2️⃣可导入其他 .proto 文件的消息并使用 -- import 3、创建通讯录 2.0 版本的 .proto 文件4、通讯录 2.0 版本的读写实现 -- 第一种验证方式5、decode选项 -- 第二种验证方式…...

React 中hooks之useLayoutEffect 用法总结以及与useEffect的区别

React useLayoutEffect 1. useLayoutEffect 基本概念 useLayoutEffect 是 React 的一个 Hook&#xff0c;它的函数签名与 useEffect 完全相同&#xff0c;但它会在所有的 DOM 变更之后同步调用 effect。它可以用来读取 DOM 布局并同步触发重渲染。 2. useLayoutEffect vs us…...

实战经验:使用 Python 的 PyPDF 进行 PDF 操作

文章目录 1. 为什么选择 PyPDF&#xff1f;2. 安装 PyPDF3. PDF 文件的合并与拆分3.1 合并 PDF 文件3.2 拆分 PDF 文件 4. 提取 PDF 文本5. 修改 PDF 元信息6. PDF 加密与解密6.1 加密 PDF6.2 解密 PDF 7. 页面旋转与裁剪7.1 旋转页面7.2 裁剪页面 8. 实战经验总结 PDF 是一种非…...

数据结构与算法之排序: LeetCode 15. 三数之和 (Ts版)

三数之和 https://leetcode.cn/problems/3sum/description/ 描述 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0请你返回所有和为 0 且不重复的三元…...

51c嵌入式~单片机~合集6

我自己的原文哦~ https://blog.51cto.com/whaosoft/13127816 一、STM32单片机的知识点总结 本文将以STM32F10x为例&#xff0c;对标准库开发进行概览。主要分为三块内容&#xff1a; STM32系统结构寄存器通过点灯案例&#xff0c;详解如何基于标准库构建STM32工程 STM3…...

SQL Server Management Studio 表内数据查询与删除指令

查询指令 //select * from 表名称 where 列名称 数据名称 select * from Card_Info where num CC3D4D删除指令&#xff0c;删除数据库有风险&#xff0c;操作不可逆&#xff0c;建议删除前备份&#xff0c;以免删错。 //Delete * from 表名称 where 列名称 数据名称 Delete f…...

Timesheet.js - 轻松打造炫酷时间表

Timesheet.js - 轻松打造炫酷时间表 前言 在现代网页设计中&#xff0c;时间表是一个常见的元素&#xff0c;用于展示项目进度、历史事件、个人经历等信息。 然而&#xff0c;创建一个既美观又功能强大的时间表并非易事。 幸运的是&#xff0c;Timesheet.js 这款神奇的 Java…...

产品经理面试题总结2025【其一】

一、产品理解与定位 1、你如何理解产品经理这个角色&#xff1f; 作为一名互联网产品经理&#xff0c;我理解这个角色的核心在于成为产品愿景的制定者和执行的推动者。具体来说&#xff0c;产品经理是连接市场、用户和技术团队之间的桥梁&#xff0c;负责理解市场需求、用户痛…...

第16章:Python TDD实现多币种货币运算

写在前面 这本书是我们老板推荐过的&#xff0c;我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后&#xff0c;我突然思考&#xff0c;对于测试开发工程师来说&#xff0c;什么才更有价值呢&#xff1f;如何让 AI 工具更好地辅助自己写代码&#xff0c;或许…...

【Web】2025-SUCTF个人wp

目录 SU_blog SU_photogallery SU_POP SU_blog 先是注册功能覆盖admin账号 以admin身份登录&#xff0c;拿到读文件的权限 ./article?filearticles/..././..././..././..././..././..././etc/passwd ./article?filearticles/..././..././..././..././..././..././proc/1…...

C++实现矩阵Matrix类 实现基本运算

本系列文章致力于实现“手搓有限元&#xff0c;干翻Ansys的目标”&#xff0c;基本框架为前端显示使用QT实现交互&#xff0c;后端计算采用Visual Studio C。 目录 Matrix类 1、public function 1.1、构造函数与析构函数 1.2、获取矩阵数值 1.3、设置矩阵 1.4、矩阵转置…...

【GORM】初探gorm模型,字段标签与go案例

GORM是什么&#xff1f; GORM 是一个Go 语言 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它让我们可以使用结构体来操作数据库&#xff0c;而无需编写SQL 语句 GORM 模型与字段标签详解 在 GORM 中&#xff0c;模型是数据库表的抽象表示&#xff0c;字段标签&am…...

html全局遮罩,通过websocket来实现实时发布公告

1.index.html代码示例 <div id"websocket" style"display:none;position: absolute;color:red;background-color: black;width: 100%;height: 100%;z-index: 100; opacity: 0.9; padding-top: 30%;padding-left: 30%; padding-border:1px; "onclick&q…...

基于VSCode+CMake+debootstrap搭建Ubuntu交叉编译开发环境

基于VSCodeCMakedebootstrap搭建Ubuntu交叉编译开发环境 1 基于debootstrap搭建目标系统环境1.1 安装必要软件包1.2 创建sysroot目录1.3 运行debootstrap1.4 挂载必要的虚拟文件系统1.5 复制 QEMU 静态二进制文件1.6 进入目标系统1.7 使用目标系统&#xff08;以安装zlog为例&a…...

C#中System.Text.Json:从入门到精通的实用指南

一、引言 在当今数字化时代&#xff0c;数据的高效交换与处理成为软件开发的核心环节。JSON&#xff08;JavaScript Object Notation&#xff09;凭借其简洁、轻量且易于读写的特性&#xff0c;已然成为数据交换领域的中流砥柱。无论是前后端数据交互&#xff0c;还是配置文件…...

【深度学习】Huber Loss详解

文章目录 1. Huber Loss 原理详解2. Pytorch 代码详解3.与 MSELoss、MAELoss 区别及各自优缺点3.1 MSELoss 均方误差损失3.2 MAELoss 平均绝对误差损失3.3 Huber Loss 4. 总结4.1 优化平滑4.2 梯度较好4.3 为什么说 MSE 是平滑的 1. Huber Loss 原理详解 Huber Loss 是一种结合…...

Maven下载配置

目录 Win下载配置maven的环境变量 Mac下载安装配置环境变量 MavenSetting.xml文件配置 Win 下载 https://maven.apache.org/ 在主页面点击Download 点击archives 最好不要下载使用新版本&#xff0c;我使用的是maven-3.6.3&#xff0c;我们点击页面下方的archives&#xff0…...

JS基础(5):运算符和语句

一.运算符 1.赋值运算符 加减乘除都是一样的&#xff0c;&#xff0c;-&#xff0c;*&#xff0c;/ 2.一元运算符&#xff1a;经常用来计数 自增&#xff1a; 每次只能加一 自减&#xff1a;-- 前置自增 后置自增 结…...

游戏引擎学习第81天

仓库:https://gitee.com/mrxiao_com/2d_game_2 或许我们应该尝试在地面上添加一些绘图 在这段时间的工作中&#xff0c;讨论了如何改进地面渲染的问题。虽然之前并没有专注于渲染部分&#xff0c;因为当时主要的工作重心不在这里&#xff0c;但在实现过程中&#xff0c;发现地…...

网络安全 | 什么是正向代理和反向代理?

关注&#xff1a;CodingTechWork 引言 在现代网络架构中&#xff0c;代理服务器扮演着重要的角色。它们在客户端和服务器之间充当中介&#xff0c;帮助管理、保护和优化数据流。根据代理的工作方向和用途&#xff0c;代理服务器可分为正向代理和反向代理。本文将深入探讨这两种…...

前缀和——模板 二维前缀和

一.题目描述 【模板】二维前缀和_牛客题霸_牛客网 二.题目解析 这道题和上一道题有点异曲同工之妙。输入一个m行n列的矩阵&#xff0c;然后进行q次操作&#xff0c;每次操作输入4个数&#xff0c;作为两个点的坐标&#xff0c;计算这两个点为对角线的矩阵的和。 三.算法原理 …...

oracle使用case when报错ORA-12704字符集不匹配原因分析及解决方法

问题概述 使用oracle的case when函数时&#xff0c;报错提示ORA-12704字符集不匹配&#xff0c;如下图&#xff0c;接下来分析报错原因并提出解决方法。 样例演示 现在有一个TESTTABLE表&#xff0c;本表包含的字段如下图所示&#xff0c;COL01字段是NVARCHAR2类型&#xff0…...

高等数学学习笔记 ☞ 定积分与积分公式

1. 定积分的基本概念 1.1 定积分的定义 1. 定义&#xff1a;设函数在闭区间上有界。在闭区间上任意插入若干个分点&#xff0c;即&#xff0c; 此时每个小区间的长度记作(不一定是等分的)。然后在每个小区间上任意取&#xff0c;对应的函数值为。 为保证每段的值(即矩形面积)无…...

MLMs之Agent:Phidata的简介、安装和使用方法、案例应用之详细攻略

MLMs之Agent&#xff1a;Phidata的简介、安装和使用方法、案例应用之详细攻略 目录 Phidata简介 Phidata安装和使用方法 1、安装 2、使用方法 (1)、认证 (2)、创建 Agent (3)、运行 Agent (4)、Agent Playground Phidata 案例应用 1、多工具 Agent 2、多模态 Agent …...

如何在不暴露MinIO地址的情况下,用Spring Boot与KKFileView实现文件预览

在现代Web应用中&#xff0c;文件预览是一项常见且重要的功能。它允许用户在不上传或下载文件的情况下&#xff0c;直接在浏览器中查看文件内容。然而&#xff0c;直接将文件存储服务&#xff08;如MinIO&#xff09;暴露给前端可能会带来安全风险。本文将介绍如何在不暴露MinI…...

ESP8266固件烧录

一、烧录原理 1、引脚布局 2、引脚定义 3、尺寸封装 4、环境要求 5、接线方式 ESP8266系列模块集成了高速GPI0和外围接口&#xff0c;这可能会导致严重的开关噪声。如果某些应用需要高功率和EMI特性&#xff0c;建议在数字I/0线上串联10到100欧姆。这可以在切换电源时抑制过冲…...

Python 模拟真人鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…...

三天急速通关Java基础知识:Day1 基本语法

三天急速通关JAVA基础知识&#xff1a;Day1 基本语法 0 文章说明1 关键字 Keywords2 注释 Comments2.1 单行注释2.2 多行注释2.3 文档注释 3 数据类型 Data Types3.1 基本数据类型3.2 引用数据类型 4 变量与常量 Variables and Constant5 运算符 Operators6 字符串 String7 输入…...

免费使用 Adobe 和 JetBrains 软件的秘密

今天想和大家聊聊如何利用 Edu 教育邮箱免费使用 Photoshop、Illustrator 等 Adobe 系列软件&#xff0c;以及 JetBrains 开发工具。 首先&#xff0c;Adobe 的软件是设计师的必备工具。无论是处理图像的 Photoshop&#xff0c;还是进行矢量设计的 Illustrator&#xff0c;它们…...

Pytorch 自学笔记(三):利用自定义文本数据集构建Dataset和DataLoader

Pytorch 自学笔记&#xff08;三&#xff09; 1. Dataset与DataLoader1.1 torch.utils.data.Dataset1.2 torch.utils.data.DataLoader Pytorch 自学笔记系列的第三篇。针对Pytorch的Dataset和DataLoader进行简单的介绍&#xff0c;同时&#xff0c;介绍如何使用自定义文本数据集…...

gradle项目的创建和基本结构简介

文章目录 创建gradle项目&#xff08;命令行&#xff09;创建gradle项目&#xff08;IDEA&#xff09;项目基本结构和功能Gradle 构建流程测试类体验 创建gradle项目&#xff08;命令行&#xff09; yangMacdeMac-mini gradleStudy % gradle init Starting a Gradle Daemon (s…...

wow-agent---Day3 Zigent 智能代理开发框架

这个框架是课程讲解的&#xff0c;但资料比较少&#xff0c;觉得框架比较小众&#xff0c;所以这里只分析代码&#xff0c;打算把更多的精力放在metagpt的学习上&#xff0c;毕竟还是要学教为主流的框架&#xff0c;这对后续维护升级都有帮助&#xff0c;当然感兴趣作为研究&am…...

python 入门

1. Python 概述 1.1 简介 python 是一种面向对象的解释型编程语言&#xff0c;由吉多范罗苏姆开发&#xff1b; 1991 年&#xff0c;公开发行版发布&#xff1b; 因其可以将其他语言制作的模块轻松联接在一起&#xff0c;又被称作胶水语言&#xff1b; 1.2 优点 简单易学&…...

sentinel微服务保护

学习链接 SpringCloudRabbitMQDockerRedis搜索分布式 文章目录 学习链接1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.超时处理1.1.3.仓壁模式1.1.4.断路器1.1.5.限流1.1.6.总结 1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel官网地址github地址…...

接口测试Day10-封装IHRM登录

-登录接口 普通方式实现 登录接口对象层 思路&#xff1a; 动态变化的&#xff0c;写入参数固定不变&#xff0c;直接写到方法实现内响应结果&#xff0c;通过返回值 return 分析&#xff1a; 封装实现&#xff1a; 登录接口测试用例层 封装断言方法 1、创建 文件 assert_uti…...

什么是IP地址、子网掩码、网关、DNS

简单解释 IP地址在网络中用于标识一个节点(或者网络设备的接口) IP地址用于IP报文在网络中的寻址 一个IPv4地址有32 bit。 IPv4地址通常采用“点分十进制”表示。 IPv4地址范围:0.0.0.0~255.255.255.255 网络部分:用来标识一个网络&#xff0c;代表IP地址所属网络。 主机部分:…...

python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测

角点检测&#xff08;Corner Detection&#xff09;是计算机视觉和图像处理中重要的步骤&#xff0c;主要用于提取图像中的关键特征&#xff0c;以便进行后续的任务&#xff0c;比如图像匹配、物体识别、运动跟踪等。下面介绍几种常用的角点检测方法及其应用。 1. Harris角点检…...

软路由系统iStoreOS 一键安装 docker compose

一键安装命令 大家好&#xff01;今天我来分享一个快速安装 docker-compose 的方法。以下是我常用的命令&#xff0c;当前版本是 V2.32.4。如果你需要最新版本&#xff0c;可以查看获取docker compose最新版本号 部分&#xff0c;获取最新版本号后替换命令中的版本号即可。 w…...

Invicti-Professional-V25.1

01 更新介绍 此更新包括对内部代理的更改。内部扫描代理的当前版本为 25.1.0。内部身份验证验证程序代理的当前版本为 25.1.0。#新功能现在&#xff0c;单击扫描摘要屏幕中的预设扫描图标会将您重定向到具有过滤视图的 “最近扫描” 页面&#xff0c;从而改进导航和对相关扫描…...

【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件

&#x1f525; 目录 1. 控件概述 控件体系的发展阶段 2. QWidget 核心属性 2.1 核心属性概览2.2 用件可用&#xff08;Enabled&#xff09; 2.3 坐标系&#xff08;Geometry&#xff09; **实例 1: 控制按钮的位置**实例 2: 表白 程序 2.4 窗口标题&#xff08;windowTiltle&a…...

Spring WebFlux

文章目录 一、概述1、Spring体系定位2、Spring MVC和WebFlux差异 二、入门1、依赖2、ReactorHttpHandlerAdapter&#xff08;main启动&#xff09;3、DispatcherHandler&#xff08;SpringWebFlux启动&#xff09;4、WebFilter 三、DispatcherHandler理解1、handle 前置知识&am…...

【AI | pytorch】torch.polar的使用

一、torch.polar的使用 torch.polar 是 PyTorch 中用来生成复数张量的一个函数&#xff0c;但它与数学中的复数表达式 ( z re^{i\theta} ) 是等价的。 具体来说&#xff0c;torch.polar(abs, angle) 接受两个实数张量参数&#xff1a; abs&#xff1a;表示复数的模长&#…...

AWTK fscript 中的 输入/出流 扩展函数

fscript 是 AWTK 内置的脚本引擎&#xff0c;开发者可以在 UI XML 文件中直接嵌入 fscript 脚本&#xff0c;提高开发效率。本文介绍一下 fscript 中的 iostream 扩展函数 1.iostream_get_istream 获取输入流对象。 原型 iostream_get_istream(iostream) > object示例 va…...

【多线程】线程池

一、什么是线程池 线程池&#xff08;Thread Pool&#xff09;是一种多线程并发执行的设计模式&#xff0c;它通过维护一个线程集合来执行多个任务&#xff0c;避免频繁地创建和销毁线程&#xff0c;提高系统性能和响应速度。 就好比如你经营了一家餐饮店&#xff0c;你名下有…...

小结:路由器配置和管理 RIP协议

华为路由器中配置和管理 RIP&#xff08;Routing Information Protocol&#xff09;的相关指令主要分为以下几个部分&#xff1a;基础配置指令、接口配置指令、路由控制指令和调试指令。以下是总结&#xff1a; 1. 启用 RIP 协议 [Huawei] rip 1rip 1&#xff1a;表示创建并启…...

基于海思soc的智能产品开发(高、中、低soc、以及和fpga的搭配)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 市场上关于图像、音频的soc其实非常多&#xff0c;这里面有高、中、低档&#xff0c;开发方式也不相同。之所以会这样&#xff0c;有价格的因素&am…...

于灵动的变量变幻间:函数与计算逻辑的浪漫交织(下)

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。 这一节我们主要来学习单个函数的声明与定义&#xff0c;static和extern… 这里写目录标题 一、单个函数…...

偷偷的学Java

序章&#xff1a;为何要偷偷学Java&#xff1f; • Java&#xff0c;不仅仅是一种编程语言 • 偷偷学Java&#xff0c;快速提升你的竞争力 •Java学习秘籍 第一章&#xff1a;Java的神秘面纱 •Java的起源与发展历程 •Java的生态系统与应用场景 • Java与其他编程语言的…...

以单用户模式启动 Linux 的方法

注&#xff1a;本文为 “Linux 启动单用户模式” 相关文章合辑。 未整理去重。 以单用户模式启动 linux 的三种方法 作者&#xff1a; Magesh Maruthamuthu 译者&#xff1a; LCTT Xiaobin.Liu 2020-05-03 23:01 单用户模式&#xff0c;也被称为维护模式&#xff0c;超级用户…...

【AI论文】生成式视频模型是否通过观看视频学习物理原理?

摘要&#xff1a;AI视频生成领域正经历一场革命&#xff0c;其质量和真实感在迅速提升。这些进步引发了一场激烈的科学辩论&#xff1a;视频模型是否学习了能够发现物理定律的“世界模型”&#xff0c;或者&#xff0c;它们仅仅是复杂的像素预测器&#xff0c;能够在不理解现实…...