当前位置: 首页 > 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类型保护的优势 使用泛型 泛型…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

如何在Windows本机安装Python并确保与Python.NET兼容

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...