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

揭秘关于TFRcord的五脏六腑

揭秘关于TFRcord的五脏六腑

前言:本篇文章将演示如何创建、解析和使用tf.Example消息,以及如何在.tfrecord文件之间对tf.Example消息进行序列化、写入和读取。

教程讲解使用的都是结构化数据,文章最后还会演示如果将图片写成.tfrecord文件,这在同个数据集用于不同模型情景之下非常有用。

官网文档是从讲原理,然后再展现示例。我觉得这种方式很容易劝退小白,因为原理晦涩难懂。这里先展示示例,然后再肢解示例,先总体再细分的思想

希望能让读者更容易理解和接受

一、如何将标量输入值变成协议消息

这里先不解释什么是协议消息,先看示例,后解释

# todo 导入相应工具包
import tensorflow as tfimport numpy as np
import IPython.display as display# todo 为了讲解,模拟生成一些数据
# 这里准备生成10000个元素
n_observations = int(1e4)# 随机生成10000个True和False布尔值
feature0 = np.random.choice([False, True], n_observations)# 随机生成10000个0-5的整数
feature1 = np.random.randint(0, 5, n_observations)# 随机生成10000个值是以下字符串的字符串
strings = np.array([b'cat', b'dog', b'chicken', b'horse', b'goat'])
feature2 = strings[feature1]# 随机生成10000个01正太分布数据,数据是浮点型
feature3 = np.random.randn(n_observations)# todo 下面分别演示将字符串类型标量、浮点型标量、整数型标量转换成协议消息
# todo 这些方法可以复制过去直接使用
def _bytes_feature(value):"""输入string / byte类型数据,返回bytes_list类型的协议消息"""if isinstance(value, type(tf.constant(0))):value = value.numpy() # BytesList won't unpack a string from an EagerTensor.return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))  # 先记住这个写法,这个写法是TF官网推荐的写法def _float_feature(value):"""输入float / double类型数据,返回float_list类型的协议消息"""return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))def _int64_feature(value):"""输入bool / enum / int / uint.类型数据,返回int64_list类型的协议消息"""return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))# todo 通过调用上面的方法可以做到将相应类型的标量转换成协议消息了
print(_bytes_feature(b'test_string'))  # 字符串
print(_bytes_feature(u'test_bytes'.encode('utf-8')))  # 二进制bytesprint(_float_feature(np.exp(1)))  # 浮点型,自然数eprint(_int64_feature(True))  # 布尔型
print(_int64_feature(1))  # 整型

结果如下。结果展示的就是协议消息的“样子”,协议消息就是长这样,协议消息对应的值就是value里面的值

bytes_list {value: "test_string"
}bytes_list {value: "test_bytes"
}float_list {value: 2.7182817459106445
}int64_list {value: 1
}int64_list {value: 1
}

二、如何将协议消息变成二进制字符串

接着上面代码的延续,先不解释什么是二进制字符串,读者先阅读一遍代码的注释

# todo 将浮点型标量转成协议消息
feature = _float_feature(np.exp(1))# todo 使用方法SerializeToString(),将协议消息变成二进制字符串
string_010 = feature.SerializeToString()print(string_010)  # 结果是:   b'\x12\x06\n\x04T\xf8-@'"""
b'\x12\x06\n\x04T\xf8-@'
就是二进制字符串的样子
你可以简单把它理解成字符串
"""

三、如何将协议消息变成字典协议消息

字典型的协议消息如下,读者先看一遍代码的注释,再进行理解一遍

# todo 构建不同类型的协议消息
bytes_fea = _bytes_feature(b'test_string')  # 字符串协议消息float_fea = _float_feature(np.exp(1))  # 浮点型协议消息int64_fea = _int64_feature(1)  # 整数型协议消息# todo 将协议消息变成字典型协议消息
dict_fea = {'featrue0':bytes_fea,'featrue1':float_fea,'featrue2':int64_fea,
}
"""
说明:
dict_fea就是字典型协议消息,其中字典的key可以顺便自己命名,而字典的value就是协议消息
"""

字典型协议消息就是字典的value就是协议消息的字典

四、如何将字典协议消息变成二进制字符串

做法就是将字典协议消息转成特征消息,因为特征消息是协议消息的一种,所以可以将特征消息根据方法SerializeToString()变成二进制字符串

# todo 构建不同类型的协议消息
bytes_fea = _bytes_feature(b'test_string')  # 字符串协议消息float_fea = _float_feature(np.exp(1))  # 浮点型协议消息int64_fea = _int64_feature(1)  # 整数型协议消息# todo 将协议消息变成字典型协议消息
dict_fea = {'featrue0':bytes_fea,'featrue1':float_fea,'featrue2':int64_fea,
}# todo 将协议消息变成特征消息,代码就是这么写的,读者根据官网推荐这些写法这么写即可
example_proto = tf.train.Example(features=tf.train.Features(feature=dict_fea))# todo 将特征消息转成二进制字符串
bytes_string = example_proto.SerializeToString()
print(bytes_string)

结果如下。显示的就是字典协议消息的二进制字符串

b'\nF\n\x1b\n\x08featrue0\x12\x0f\n\r\n\x0btest_string\n\x14\n\x08featrue1\x12\x08\x12\x06\n\x04T\xf8-@\n\x11\n\x08featrue2\x12\x05\x1a\x03\n\x01\x01'

五、关于TFRecord文件各种疑问

  • 什么是TFRecord文件

    TFRecord 格式是一种用于存储二进制字符串记录序列的简单格式。

  • 为什么要用TFRecord文件

    通过tfrecord文件建立的数据管道Dataset对象读数的性能更好

  • TFRecord格式详细信息

    TFRecord 文件包含一系列记录。该文件只能按顺序读取。

    每条记录包含一个字节字符串(用于数据有效负载),外加数据长度,以及用于完整性检查的 CRC32C(使用 Castagnoli 多项式的 32 位 CRC)哈希值。

    每条记录会存储为以下格式:

    uint64 length uint32 masked_crc32_of_length byte   data[length] uint32 masked_crc32_of_data
    

    将记录连接起来以生成文件。此处对 CRC 进行了说明,且 CRC 的掩码为:

    masked_crc = ((crc >> 15) | (crc << 17)) + 0xa282ead8ul
    

    注:不需要在 TFRecord 文件中使用 tf.Exampletf.Example 只是将字典序列化为字节字符串的一种方法。文本行、编码的图像数据,或序列化的张量(使用 tf.io.serialize_tensor,或在加载时使用 tf.io.parse_tensor)。有关更多选项,请参阅 tf.io 模块。

六、TFRecord文件如何存储数据

TFRecord文件存储的是二进制字符串,二进制字符串由协议消息或者是字典协议消息生成,协议消息又由标量或者是向量生成。

所以TFRecord存储的二进制字符串相当于存储了真实的数据

之所以要通过协议消息、字典协议消息来存储这些数据,是因为这样子可以提高数据的复用率和使用效率

七、将numpy数据存储成TFRecord格式文件

读者可以直接阅读代码的注释.从上往下阅读即可,不需要觉得很难

# todo 导入相应工具包
import tensorflow as tfimport numpy as np
import IPython.display as display# todo 为了讲解,模拟生成一些数据
# 这里准备生成10000个元素
n_observations = int(1e4)# 随机生成10000个True和False布尔值
feature0 = np.random.choice([False, True], n_observations)# 随机生成10000个0-5的整数
feature1 = np.random.randint(0, 5, n_observations)# 随机生成10000个值是以下字符串的字符串
strings = np.array([b'cat', b'dog', b'chicken', b'horse', b'goat'])
feature2 = strings[feature1]# 随机生成10000个01正太分布数据,数据是浮点型
feature3 = np.random.randn(n_observations)# todo 下面分别演示将字符串类型标量、浮点型标量、整数型标量转换成协议消息
# todo 这些方法可以复制过去直接使用
def _bytes_feature(value):"""输入string / byte类型数据,返回bytes_list类型的协议消息"""if isinstance(value, type(tf.constant(0))):value = value.numpy() # BytesList won't unpack a string from an EagerTensor.return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))  # 先记住这个写法,这个写法是TF官网推荐的写法def _float_feature(value):"""输入float / double类型数据,返回float_list类型的协议消息"""return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))def _int64_feature(value):"""输入bool / enum / int / uint.类型数据,返回int64_list类型的协议消息"""return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))def serialize_example(feature0, feature1, feature2, feature3):"""输入标量,转成字典协议消息,转成特征消息,转成二进制字符串"""# 构建字典协议消息feature = {'feature0': _int64_feature(feature0),'feature1': _int64_feature(feature1),'feature2': _bytes_feature(feature2),'feature3': _float_feature(feature3),}# Create a Features message using tf.train.Example.example_proto = tf.train.Example(features=tf.train.Features(feature=feature))return example_proto.SerializeToString()# todo 将二进制字符串写进tfrecord文件中
filename = './test.tfrecord'
with tf.io.TFRecordWriter(filename) as writer:  # 构建一个写入对象的上下文for i in range(n_observations):  # 循环写入example = serialize_example(feature0[i], feature1[i], feature2[i], feature3[i])writer.write(example)
<ipython-input-62-e109c8c4da87>:38: DeprecationWarning: In future, it will be an error for 'np.bool_' scalars to be interpreted as an indexreturn tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

从上面可以看出来,上面的代码需要循环写入数据,速度比较慢,下面介绍一种速度更加快速的写入方法

八、通过Dataset将numpy数据存储成TFRecord格式文件

过程代码解释了原理,并且这些代码都可以进行复用,请读者认真消化

# todo 导入相应工具包
import tensorflow as tfimport numpy as np
import IPython.display as display# todo 为了讲解,模拟生成一些数据
# 这里准备生成10000个元素
n_observations = int(1e4)# 随机生成10000个True和False布尔值
feature0 = np.random.choice([False, True], n_observations)# 随机生成10000个0-5的整数
feature1 = np.random.randint(0, 5, n_observations)# 随机生成10000个值是以下字符串的字符串
strings = np.array([b'cat', b'dog', b'chicken', b'horse', b'goat'])
feature2 = strings[feature1]# 随机生成10000个01正太分布数据,数据是浮点型
feature3 = np.random.randn(n_observations)# todo 下面分别演示将字符串类型标量、浮点型标量、整数型标量转换成协议消息
# todo 这些方法可以复制过去直接使用
def _bytes_feature(value):"""输入string / byte类型数据,返回bytes_list类型的协议消息"""if isinstance(value, type(tf.constant(0))):value = value.numpy() # BytesList won't unpack a string from an EagerTensor.return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))  # 先记住这个写法,这个写法是TF官网推荐的写法def _float_feature(value):"""输入float / double类型数据,返回float_list类型的协议消息"""return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))def _int64_feature(value):"""输入bool / enum / int / uint.类型数据,返回int64_list类型的协议消息"""return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))def serialize_example(feature0, feature1, feature2, feature3):"""输入标量,转成字典协议消息,转成特征消息,转成二进制字符串"""# 构建字典协议消息feature = {'feature0': _int64_feature(feature0),'feature1': _int64_feature(feature1),'feature2': _bytes_feature(feature2),'feature3': _float_feature(feature3),}# Create a Features message using tf.train.Example.example_proto = tf.train.Example(features=tf.train.Features(feature=feature))return example_proto.SerializeToString()# todo 构建Dataset对象
features_dataset = tf.data.Dataset.from_tensor_slices((feature0, feature1, feature2, feature3))def tf_serialize_example(f0,f1,f2,f3):tf_string = tf.py_function(  # py_function函数将python函数转成可以通过tf计算图进行运算的函数,提升速度的关键就是在此serialize_example,(f0,f1,f2,f3),  # 传到函数serialize_example的参数tf.string)      # 指定函数serialize_example返回值的类型return tf.reshape(tf_string, ()) # 返回结果# todo 构建一个生成器
def generator():for features in features_dataset:yield serialize_example(*features)if True:# todo 通过map函数将函数tf_serialize_example作用到features_dataset对象中的每个元素中,生成一个新的Dataset对象serialized_features_dataset = features_dataset.map(tf_serialize_example)
else:# todo 也可以直接通过生成器构建需要的Dataset对象serialized_features_dataset = tf.data.Dataset.from_generator(generator, # 可调用的生成器函数output_types=tf.string, # 输出数据的类型output_shapes=()   # 输出数据的形状)# todo 通过Dataset对象,将数据存储成TFRecord格式文件
filename = 'test.tfrecord'
writer = tf.data.experimental.TFRecordWriter(filename)
writer.write(serialized_features_dataset)

九、通过Dataset对象读取TFRecord格式文件

过程代码解释了原理,并且这些代码都可以进行复用,请读者认真消化。定义特征描述,这个非常重要,主要是定义了特征描述的形状和类型


# 将TFRecord文件读成Dataset对象
filenames = [filename]
raw_dataset = tf.data.TFRecordDataset(filenames)# todo 定义特征描述,这个非常重要,格式如下,主要是定义了特征描述的形状和类型
feature_description = {'feature0': tf.io.FixedLenFeature([], tf.int64, default_value=0),'feature1': tf.io.FixedLenFeature([], tf.int64, default_value=0),'feature2': tf.io.FixedLenFeature([], tf.string, default_value=''),'feature3': tf.io.FixedLenFeature([], tf.float32, default_value=0.0),
}def _parse_function(example_proto):# 将二进制字符串转成实际的存储数据return tf.io.parse_single_example(example_proto, feature_description)# 运用map函数将函数_parse_function作用到Dataset对象的每个元素里面
parsed_dataset = raw_dataset.map(_parse_function)# parsed_dataset对象的每个元素就是真实的存储数据
for parsed_record in parsed_dataset.take(10):print(repr(parsed_record))break

结果如下

{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=2>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'chicken'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-0.10460473>}

10、欢迎关注,下期讲解使用TFRecord文件读取和写入图像数据

相关文章:

揭秘关于TFRcord的五脏六腑

揭秘关于TFRcord的五脏六腑 前言&#xff1a;本篇文章将演示如何创建、解析和使用tf.Example消息&#xff0c;以及如何在.tfrecord文件之间对tf.Example消息进行序列化、写入和读取。 教程讲解使用的都是结构化数据&#xff0c;文章最后还会演示如果将图片写成.tfrecord文件&am…...

【Shell学习笔记】3.Shell 传递参数及数组

前言 本章介绍Shell的传递参数和数组。 Shell 传递参数 我们可以在执行 Shell 脚本时&#xff0c;向脚本传递参数&#xff0c;脚本内获取参数的格式为&#xff1a;$n。n 代表一个数字&#xff0c;1 为执行脚本的第一个参数&#xff0c;2 为执行脚本的第二个参数&#xff0c;…...

【终结Bug】ModuleNotFoundError: No module named ‘cv2’

解决方案&#xff1a; 打开 cmd键入 pip install opencv_python -i https://pypi.tuna.tsinghua.edu.cn/simple...

SQL Server2008详细安装步骤(保姆式教程)

安装包下载 链接&#xff1a;https://pan.baidu.com/s/1Rjx4DHJBeCW2asC_4Kzo6Q?pwdchui 提取码&#xff1a;chui 安装过程 1.解压后使用管理员身份打开安装程序 2.选择全新安装或向现有安装添加新功能 3.确认 4.输入产品密钥&#xff08;上方网盘安装包里有&#xff0…...

Linux常用操作

Linux常用操作 前言常用命令&#xff1a;一些操作命令&#xff1a;前言 本文是笔者在使用cadence的过程中&#xff0c;操作linux的笔记&#xff0c;仅记录个人常用&#xff0c;持续更新 常用命令&#xff1a; &#xff08;1&#xff09;高频&#xff1a;会了这几个就能在文件…...

Golang 处理parquet文件实战教程

Parquet是Apache基金会支持的项目&#xff0c;是面向列存储二进制文件格式。支持不同类型的压缩方式&#xff0c;广泛用于数据科学和大数据环境&#xff0c;如Hadoop生态。 本文主要介绍Go如何生成和处理parquet文件。 创建结构体 首先创建struct&#xff0c;用于表示要处理…...

腾讯TIM实现即时通信 v3+ts实践

目录 初始化sdk 功能描述 初始化 准备 SDKAppID 调用初始化接口 监听事件 发送消息 创建消息 创建文本消息 登录登出 功能描述 登录 登出 销毁 登录设置 获取会话列表 功能描述 获取会话列表 获取全量的会话列表 历史消息 功能描述 拉取消息列表 分页拉取…...

华为OD机试 - 回文字符串(Java JS Python)

题目描述 如果一个字符串正读和反渎都一样(大小写敏感),则称它为一个「回文串」,例如: leVel是一个「回文串」,因为它的正读和反读都是leVel;同理a也是「回文串」art不是一个「回文串」,因为它的反读tra与正读不同Level不是一个「回文串」,因为它的反读leveL与正读不…...

APP测试的7大注意点。

1. 运行 1&#xff09; App安装完成后的试运行&#xff0c;可正常打开软件。 2&#xff09; App打开测试&#xff0c;是否有加载状态进度提示。 3&#xff09; App⻚面间的切换是否流畅&#xff0c;逻辑是否正确。 4&#xff09; 注册 同表单编辑⻚面 用户名密码⻓度 …...

设计模式-第4章(装饰模式)

装饰模式装饰模型装饰模式示例商场收银程序&#xff08;简单工厂策略装饰模式实现&#xff09;装饰模式总结装饰模型 装饰模式&#xff08;Decorator&#xff09;&#xff0c;动态地给一个对象添加一些额外的职责&#xff0c;就增加功能来说&#xff0c;装饰模式比生成子类更为…...

【算法设计-分治】快速幂与龟速乘

文章目录1. 快速幂2. 龟速乘3. 快速幂取模4. 龟速乘取模5. 快速幂取模优化1. 快速幂 算法原理&#xff1a; 计算 311&#xff1a; 311 (35)2 x 335 (32)2 x 332 3 x 3仅需计算 3 次&#xff0c;而非 11 次 计算 310&#xff1a; 310 (35)235 (32)2 x 332 3 x 3仅需计算…...

基于新一代kaldi项目的语音识别应用实例

本文是由郭理勇在第二届SH语音技术研讨会和第七届Kaldi技术交流会上对新一代kaldi项目在学术及“部署”两个方面报告的内容上的整理。如果有误&#xff0c;欢迎指正。 文字整理丨李泱泽 编辑丨语音小管家 喜报&#xff1a;新一代Kaldi团队三篇论文均被语音顶会ICASSP-2023接…...

【GO】31.grpc 客户端负载均衡源码分析

这篇文章是记录自己查看客户端grpc负载均衡源码的过程&#xff0c;并没有太详细的讲解&#xff0c;参考价值不大&#xff0c;可以直接跳过&#xff0c;主要给自己看的。一.主要接口&#xff1a;Balancer Resolver1.Balancer定义Resolver定义具体位置为1.grpc源码对解析器(resol…...

PTA L1-058 6翻了(详解)

前言&#xff1a;内容包括&#xff1a;题目&#xff0c;代码实现&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; “666”是一种网络用语&#xff0c;大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字“9”&#xff0c;意思是“6翻了”&#xff0…...

【Origin科研绘图】如何快速绘制一个折线图 ||【前端特效】爱心篇 之 幸好有你 || 泰坦尼克号——乘客生存与否 预测 || PyCharm使用介绍

🎯作者主页:追光者♂ 🌸个人简介:在读计算机专业硕士研究生、CSDN-人工智能领域新星创作者🏆、2022年CSDN博客之星人工智能领域TOP4🌟、阿里云社区专家博主🏅 【无限进步,一起追光!】 🍎欢迎点赞👍 收藏⭐ 留言📝 🌿本篇,首先是:基于科研绘图工具O…...

一文解读电压放大器(电压放大器原理)

关于电压放大器的科普知识&#xff0c;之前讲过很多&#xff0c;今天为大家汇总一篇文章来详细的讲解电压放大器&#xff0c;希望大家对于电压放大器能有更清晰的认识。电压放大器是什么&#xff1a;电压放大器是一种常用的电子器件&#xff0c;它的主要作用是把输入信号的振幅…...

线上监控诊断神器arthas

目录 什么是arthas 常用命令列表 1、dashboard仪表盘 2、heapdump dumpJAVA堆栈快照 3、jvm 4、thread 5、memory 官方文档 安装使用 1、云安装arthas 2、获取需要监控进程ID 3、运行arthas 4、进入仪表盘 5、其他命令使用查看官方文档 什么是arthas arthas是阿…...

@Import注解的原理

此注解是springboot自动注入的关键注解&#xff0c;所以拿出来单独分析一下。 启动类的run方法跟进去最终找到refresh方法&#xff1b; 这里直接看这个org.springframework.context.support.AbstractApplicationContext#refresh方法即可&#xff0c;它下面有一个方法 invoke…...

平台总线开发(id和设备树匹配)

目录 一、ID匹配之框架代码 二、ID匹配之led驱动​​​​​​​ 三、设备树匹配 四、设备树匹配之led驱动 五、一个编写驱动用的宏 一、ID匹配之框架代码 id匹配&#xff08;可想象成八字匹配&#xff09;&#xff1a;一个驱动可以对应多个设备 ------优先级次低 注意事项…...

TS泛型,原来就这?

一、泛型是什么&#xff1f;有什么作用&#xff1f; 当我们定义一个变量不确定类型的时候有两种解决方式&#xff1a; 使用any 使用any定义时存在的问题&#xff1a;虽然知道传入值的类型但是无法获取函数返回值的类型&#xff1b;另外也失去了ts类型保护的优势 使用泛型 泛型…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

JavaScript 标签加载

目录 JavaScript 标签加载script 标签的 async 和 defer 属性&#xff0c;分别代表什么&#xff0c;有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...

Modbus转Ethernet IP深度解析:磨粉设备效率跃升的底层技术密码

在建材矿粉磨系统中&#xff0c;开疆智能Modbus转Ethernet IP网关KJ-EIP-101的应用案例是一个重要的技术革新。这个转换过程涉及到两种主要的通信协议&#xff1a;Modbus和Ethernet IP。Modbus是一种串行通信协议&#xff0c;广泛应用于工业控制系统中。它简单、易于部署和维护…...

C++ 变量和基本类型

1、变量的声明和定义 1.1、变量声明规定了变量的类型和名字。定义初次之外&#xff0c;还申请存储空间&#xff0c;也可能会为变量赋一个初始值。 如果想声明一个变量而非定义它&#xff0c;就在变量名前添加关键字extern&#xff0c;而且不要显式地初始化变量&#xff1a; e…...

2025年上海市“星光计划”第十一届职业院校技能大赛 网络安全赛项技能操作模块样题

2025年上海市“星光计划”第十一届职业院校技能大赛 网络安全赛项技能操作模块样题 &#xff08;二&#xff09;模块 A&#xff1a;安全事件响应、网络安全数据取证、应用安全、系统安全任务一&#xff1a;漏洞扫描与利用:任务二&#xff1a;Windows 操作系统渗透测试 :任务三&…...