C++plog库,轻量级日志框架(日志库)

news/2024/4/26 5:06:24/文章来源:https://blog.csdn.net/Dontla/article/details/129183893

文章目录

    • 主要头文件及使用方法解释
      • plog/Log.h
      • plog/Appenders/ColorConsoleAppender.h
      • plog/Appenders/RollingFileAppender.h
      • plog/Formatters/TxtFormatter.h
    • 三个核心概念
      • Formatter:格式化程序
        • 格式化程序举例
          • TxtFormatter
          • JsonFormatter
          • CsvFormatter
          • SyslogFormatter
      • Appender:输出器
        • 输出器举例
          • ConsoleAppender
          • RollingFileAppender
          • DailyRollingFileAppender
          • UdpAppender
          • SyslogAppender
          • NullAppender
      • Logger:记录器
        • 使用指定级别记录器过滤日志示例1(支持多个记录器输出,每个记录器单独配置输出方式)
        • 使用指定级别记录器过滤日志示例2(最常用最简单用法,只需初始化一次,其他源文件导入头文件即可用)(★★★★★)
    • 使用方法
      • 简单入门
        • 单个源文件打印日志
          • 日志输出内容解析`2023-02-27 10:19:20.384 DEBUG [5461] [main@11] Hello log!`
        • 多个源文件打印到同一日志文件(只需初始化一次)
        • 多个源文件打印到不同日志文件(multiple loggers)
        • 日志打印到多个输出器(multiple appenders)
        • 输出彩色日志到控制台
    • 其他说明
      • 当代码中包含多个初始化文件时,调用plog怎么知道输出到哪个初始化文件?
      • 当plog::init()函数中的maxFileSize和maxFiles参数任一为0,取消滚动打印功能(它们默认就是0)
      • 延迟流评估是什么?(Lazy stream evaluation)
      • 自动捕获'this'指针功能有什么用?

因为合作方cw提供的库里有个plog,所以查询一下plog的使用方法

具体详细使用方法可以参考:C/C++ plog日志简单用法

主要头文件及使用方法解释

plog/Log.h

这是 plog 库的核心头文件,其中定义了 plog::Logger 类和一些与日志相关的函数和宏定义。使用这个头文件可以满足大部分的日志需求。

plog/Appenders/ColorConsoleAppender.h

这个头文件定义了一个彩色控制台输出的日志附加器,可以将日志以彩色输出到控制台。如果你需要在控制台上打印带有颜色的日志,可以使用这个头文件。

plog/Appenders/RollingFileAppender.h

这个头文件定义了一个滚动文件输出的日志附加器,可以将日志写入到滚动的日志文件中。如果你需要将日志保存到文件中,并且希望文件不会无限制增长,可以使用这个头文件。

plog/Formatters/TxtFormatter.h

这个头文件定义了一个简单的文本格式化器,可以将日志以文本格式输出。如果你不需要复杂的日志格式,可以使用这个头文件。

你可以根据自己的需要选择引入相应的头文件,例如:

#include <plog/Log.h>  // 使用 plog 的核心功能
#include <plog/Appenders/ColorConsoleAppender.h>  // 如果需要彩色输出
#include <plog/Appenders/RollingFileAppender.h>   // 如果需要输出到滚动文件
#include <plog/Formatters/TxtFormatter.h>          // 如果需要简单文本格式输出

一般情况下,只需要引入 plog/Log.h 头文件即可使用 plog 的基本功能,如果需要额外的功能,再引入相应的头文件即可。

三个核心概念

Formatter:格式化程序

用于将日志消息转换为特定格式的字符串,以便记录和输出。plog提供了几种内置格式化程序,如TXT、CSV、FuncMessage和MessageOnly,用户还可以自定义自己的格式化程序。

格式化程序举例

除了下面几种 Formatter,Plog 还提供了一些其他的 Formatter,如 BsonFormatter、XMLFormatter 等。用户可以根据实际需求选择适合的 Formatter 进行使用。

TxtFormatter

TxtFormatter 是 Plog 的默认 Formatter。它将日志信息格式化为一个文本字符串,并添加一些元信息(如时间戳、日志级别等)。TxtFormatter 格式化的文本字符串可以被写入文本文件或控制台输出。TxtFormatter 可以通过设置不同的参数(如是否包含时间戳、是否包含线程 ID 等)进行定制化。

JsonFormatter

JsonFormatter 将日志信息格式化为 JSON 格式的字符串。它可以让日志信息更方便地与其他系统进行交互。JsonFormatter 的输出结果可以被写入文本文件或控制台输出。JsonFormatter 可以通过设置不同的参数(如是否包含时间戳、是否包含线程 ID 等)进行定制化。

CsvFormatter

CsvFormatter 将日志信息格式化为 CSV(Comma-Separated Values)格式的字符串。它可以让日志信息更方便地进行导出和分析。CsvFormatter 的输出结果可以被写入文本文件或控制台输出。CsvFormatter 可以通过设置不同的参数(如是否包含时间戳、是否包含线程 ID 等)进行定制化。

SyslogFormatter

SyslogFormatter 将日志信息格式化为 Syslog 协议规定的格式。Syslog 是一种常见的日志协议,可以让日志信息被发送到远程 syslog 服务器。SyslogFormatter 可以通过设置不同的参数(如 Syslog 服务器地址、Syslog 设备标识符等)进行定制化。

Appender:输出器

用于将格式化后的日志消息输出到目标位置,例如控制台、文件、系统日志等。plog提供了几种内置输出器,如RollingFile、Console、ColorConsole、Android、EventLog、DebugOutput和DynamicAppender,用户还可以自定义自己的输出器。

输出器举例

每个Appender都有自己的优点和用途。ConsoleAppender可用于快速测试和调试,RollingFileAppender可用于将日志记录保留在磁盘上,DailyRollingFileAppender可用于按日期存档日志记录,UdpAppender可用于将日志记录发送到远程服务器,而SyslogAppender可用于与类UNIX系统的syslog集成。

可以根据需要使用这些Appender中的任意一个或多个。通常,您可以在一个应用程序中同时使用多个Appender。例如,您可以将日志记录输出到文件和控制台,或将日志记录发送到远程服务器和syslog。

ConsoleAppender

将日志输出到控制台,支持彩色输出。

RollingFileAppender

将日志记录输出到文件,并自动轮转日志文件。支持按文件大小、文件数和日期自动轮转。

DailyRollingFileAppender

将日志记录输出到文件,并根据日期轮转日志文件。

UdpAppender

将日志记录输出到UDP socket。

SyslogAppender

将日志记录输出到syslog(适用于类UNIX系统)。

NullAppender

不将日志记录输出到任何地方。

Logger:记录器

plog支持多个日志级别,可以使用不同级别的记录器输出不同级别的日志。在plog中,有以下几个预定义的日志级别(按照严重程度递增排列):

  • verbose:最低级别的日志,通常用于输出详细的调试信息。
  • debug:用于调试,输出程序的运行状态信息。
  • info:输出普通信息。
  • warning:输出警告信息。
  • error:输出错误信息。
  • fatal:最高级别的日志,输出致命错误信息,通常会导致程序崩溃。

在使用plog时,可以通过设置记录器的级别来控制输出的日志级别。例如,如果只想输出warning级别及以上的日志,可以将记录器的级别设置为warning,这样所有warning、error和fatal级别的日志都会被输出,而info、debug和verbose级别的日志则会被忽略。

使用指定级别记录器过滤日志示例1(支持多个记录器输出,每个记录器单独配置输出方式)

#include <plog/Log.h>
#include "plog/Initializers/RollingFileInitializer.h"enum // Define log instances. Default is 0 and is omitted from this enum.
{debugLogger = 1,infoLogger = 2
};int main() {// 创建文件输出的记录器plog::RollingFileAppender<plog::TxtFormatter> fileAppender("log.txt", 1024 * 1024, 5);// 创建debug级别的记录器,同时将日志输出到文件plog::init<debugLogger>(plog::debug, &fileAppender);// 创建info级别的记录器,同时将日志输出到文件plog::init<infoLogger>(plog::info, &fileAppender);//注:info级别比debug高// 1. 使用debug级别的记录器输出debug级别的日志PLOG_DEBUG_(debugLogger) << "PLOG_DEBUG message >> debugLogger";// 2. 使用info级别的记录器输出debug级别的日志PLOG_DEBUG_(infoLogger) << "PLOG_DEBUG message >> infoLogger";  //没输出到文件// 3. 使用debug级别的记录器输出info级别的日志PLOG_INFO_(debugLogger) << "PLOG_INFO message >> debugLogger";// 4. 使用info级别的记录器输出info级别的日志PLOG_INFO_(infoLogger) << "PLOG_INFO message >> infoLogger";return 0;
}

编译运行结果:

在这里插入图片描述

使用指定级别记录器过滤日志示例2(最常用最简单用法,只需初始化一次,其他源文件导入头文件即可用)(★★★★★)

#include <plog/Log.h>
#include "plog/Initializers/RollingFileInitializer.h"int main()
{plog::init(plog::warning, "logfile.txt");PLOG_VERBOSE << "verbose log";          // 不会输出PLOG_DEBUG << "debug log";              // 不会输出PLOG_INFO << "info log";                // 不会输出PLOG_WARNING << "warning log";          // 会输出PLOG_ERROR << "error log";              // 会输出PLOG_FATAL << "fatal log";              // 会输出return 0;
}

编译运行结果:

在这里插入图片描述

使用方法

简单入门

下载源码:https://github.com/SergiusTheBest/plog/releases/tag/1.1.9

在这里插入图片描述

单个源文件打印日志

然后在系统上新建文件夹,把上面include拷贝进去,目录结构大致这样:

在这里插入图片描述

然后源文件和编译文件长这样(源文件代码我是从上面README.md拷的):

(testPlog.cpp)

#include <plog/Log.h> // Step1: include the headers	//引入头文件
#include "plog/Initializers/RollingFileInitializer.h"int main()
{plog::init(plog::debug, "Hello.txt"); // Step2: initialize the logger //初始化logger// Step3: write log messages using a special macro	//使用特殊宏写入日志消息// There are several log macros, use the macro you liked the most	//有几个日志宏,请使用您最喜欢的宏PLOGD << "Hello log!"; // short macro	//短宏PLOG_DEBUG << "Hello log!"; // long macro	//长宏PLOG(plog::debug) << "Hello log!"; // function-style macro	//函数样式宏// Also you can use LOG_XXX macro but it may clash with other logging libraries	//也可以使用LOG_XXX宏,但它可能与其他日志库冲突(建议不用下面几种,除非有特殊情况)LOGD << "Hello log!"; // short macroLOG_DEBUG << "Hello log!"; // long macroLOG(plog::debug) << "Hello log!"; // function-style macroreturn 0;
}

(build.sh)

g++ -std=c++14 testPlog.cpp -I./include 

给build.sh添加可执行权限后,运行它编译,多出个a.out文件:

./build.sh

然后运行a.out,目录下多出个日志文件:

在这里插入图片描述
查看Hello.txt内容:

在这里插入图片描述

日志输出内容解析2023-02-27 10:19:20.384 DEBUG [5461] [main@11] Hello log!

plog输出的内容“2023-02-27 10:19:20.384 DEBUG [5461] [main@11] Hello log!" 可以解释为:

  • 2023-02-27 10:19:20.384 是记录日志的时间戳,格式为“年-月-日 时:分:秒.毫秒”。
  • DEBUG 是日志的级别,表示这是一条 DEBUG 级别的日志。
  • [5461] 表示当前线程的 ID,用方括号括起来。
  • [main@11] 表示当前函数的名称和行号,用方括号括起来。在这个示例中,函数名是 main,行号是 11。
  • Hello log! 是实际的日志内容,即我们调用 LOG_DEBUG 输出的字符串。

多个源文件打印到同一日志文件(只需初始化一次)

目录结构:
在这里插入图片描述

(testPlog.cpp)

#include <plog/Log.h> // Step1: include the headers
#include "plog/Initializers/RollingFileInitializer.h"#include "myFunc.h"int main()
{plog::init(plog::debug, "Hello.txt"); // Step2: initialize the logger// Step3: write log messages using a special macro// There are several log macros, use the macro you liked the mostPLOGD << "Hello log!"; // short macroPLOG_DEBUG << "Hello log!"; // long macroPLOG(plog::debug) << "Hello log!"; // function-style macrofunc();return 0;
}

(myFunc.cpp)

#include "myFunc.h"int func()
{PLOGD << "Hello log!"; // short macroPLOG_DEBUG << "Hello log!"; // long macroPLOG(plog::debug) << "Hello log!"; // function-style macroreturn 0;
}

(myFunc.h)

#ifndef FUNCTION_H_
#define FUNCTION_H_#include <plog/Log.h>int func();#endif // FUNCTION_H_

(build.sh)

g++ -std=c++14 *.cpp -I./include 

还是跟上面一样,./build.sh && ./a.out编译运行,打开结果日志文件Hello.txt查看结果:

在这里插入图片描述

多个源文件打印到不同日志文件(multiple loggers)

这里没用多个源文件哈,但效果也差不多,初始化时,将枚举值作为参数传入,打印时也将枚举值带上,就能输出到指定文件了

(testPlog.cpp)

//
// MultiInstance - shows how to use multiple logger instances, each instance has its own independent configuration.
//#include <plog/Log.h>
#include <plog/Initializers/RollingFileInitializer.h>enum // Define log instances. Default is 0 and is omitted from this enum.
{SecondLog = 1
};int main()
{plog::init(plog::debug, "MultiInstance-default.txt"); // Initialize the default logger instance.plog::init<SecondLog>(plog::debug, "MultiInstance-second.txt"); // Initialize the 2nd logger instance.// Write some messages to the default log.PLOGD << "Hello default log!";PLOG_DEBUG << "Hello default log!";PLOG(plog::debug) << "Hello default log!";// Write some messages to the 2nd log.PLOGD_(SecondLog) << "Hello second log!";PLOG_DEBUG_(SecondLog) << "Hello second log!";PLOG_(SecondLog, plog::debug) << "Hello second log!";return 0;
}

(build.sh)

g++ -std=c++14 *.cpp -I./include 

编译运行:

./build.sh

结果:

在这里插入图片描述

日志打印到多个输出器(multiple appenders)

目录结构:

在这里插入图片描述

(testPlog.cpp)

#include <plog/Log.h> // Step1: include the headers
#include "plog/Initializers/RollingFileInitializer.h"
#include "plog/Initializers/ConsoleInitializer.h"int main()
{static plog::RollingFileAppender<plog::CsvFormatter> fileAppender("MultiAppender.csv", 8000, 3); // Create the 1st appender.static plog::RollingFileAppender<plog::TxtFormatter> fileAppender2("MyTxtFormatter.txt", 8000, 3); // Create the 2st appender.static plog::ConsoleAppender<plog::TxtFormatter> consoleAppender; // Create the 3nd appender.plog::init(plog::debug, &fileAppender).addAppender(&fileAppender2).addAppender(&consoleAppender); // Initialize the logger with the appenders.PLOGD << "Hello log!"; // short macroPLOG_DEBUG << "Hello log!"; // long macroPLOG(plog::debug) << "Hello log!"; // function-style macroreturn 0;
}

(build.sh)

g++ -std=c++14 *.cpp -I./include 

编译运行:

./build.sh

结果:

在这里插入图片描述

可以看到,相同的日志被输出到了多个地方,1是打印到了控制台,2是MultiAppender.csv文件,3是MyTxtFormatter.txt

输出彩色日志到控制台

//
// ColorConsole - shows how to use a color console appender.
//#include <plog/Log.h>
#include <plog/Init.h>
#include <plog/Formatters/TxtFormatter.h>
#include <plog/Appenders/ColorConsoleAppender.h>int main()
{static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;plog::init(plog::verbose, &consoleAppender);// Log severity levels are printed in different colors.PLOG_VERBOSE << "This is a VERBOSE message";PLOG_DEBUG << "This is a DEBUG message";PLOG_INFO << "This is an INFO message";PLOG_WARNING << "This is a WARNING message";PLOG_ERROR << "This is an ERROR message";PLOG_FATAL << "This is a FATAL message";return 0;
}

编译运行结果:

在这里插入图片描述

其他说明

当代码中包含多个初始化文件时,调用plog怎么知道输出到哪个初始化文件?

当在多个源文件中使用PLOGD等宏时,plog会自动查找最近的plog::init初始化函数并将日志写入该函数指定的日志文件。如果在多个源文件中使用相同的plog::init初始化函数,则所有日志消息都将写入同一个文件。

在plog库中,日志输出器的初始化函数是通过C++静态初始化的方式进行注册的。在程序启动时,这些初始化函数会被按照它们的定义顺序执行,将日志输出器注册到全局日志器中。在编译时,编译器会将所有的初始化函数按照它们的定义顺序加入到可执行文件的初始化段(.init_array),在程序运行时会自动执行这些函数。

当程序执行到某个PLOG宏的时候,plog会从当前函数所在的源文件向上遍历所有调用栈帧,查找是否有已经注册的日志输出器,如果有,则使用最近的一个输出器进行输出。这个查找过程并不会通过文件系统来实现,而是通过静态初始化过程中生成的初始化段来完成。因此,plog不会查找文件系统来确定最近的日志输出器,而是通过静态链接关系来查找。如果没有找到已注册的日志输出器,则会使用默认的输出器。

因此,可以在不同的源文件中通过不同的初始化函数来初始化不同的日志输出器,并在运行时通过PLOG宏来输出日志,plog会根据静态链接关系找到最近的输出器来进行输出。

根据我的测试,当代码中包含多个初始化文件时,而打印时又没指定是哪一个,打印会把所有文件,都输出一次

当plog::init()函数中的maxFileSize和maxFiles参数任一为0,取消滚动打印功能(它们默认就是0)

Logger& init(Severity maxSeverity, const char/wchar_t* fileName, size_t maxFileSize = 0, int maxFiles = 0);
  • maxFileSize - the maximum log file size in bytes(单个日志文件最大字节数)
  • maxFiles - a number of log files to keep(滚动打印维持的最大日志文件数量)

延迟流评估是什么?(Lazy stream evaluation)

延迟流评估(Lazy stream evaluation)是一种日志记录技术,可以将日志消息的格式化延迟到实际需要输出消息时再进行,以提高性能和降低资源占用。

在使用延迟流评估技术时,当用户使用日志记录器记录一条消息时,不会立即将消息转换为字符串格式,而是将消息的内容保存到一个缓存区中,直到真正需要输出消息时,才将缓存区中的内容格式化为字符串,然后输出到目标位置。

使用延迟流评估技术可以有效减少不必要的字符串格式化操作,从而提高程序的性能和响应速度。同时,由于延迟流评估只在需要输出消息时才进行格式化,因此可以避免无效的日志记录对系统性能和资源的影响。

在plog日志库中,延迟流评估是一种可选功能,用户可以根据需要选择是否启用它。默认情况下,plog启用延迟流评估,并提供了相应的支持。

自动捕获’this’指针功能有什么用?

自动捕获’this’指针是一种日志记录技术,用于自动记录当前对象的指针,以便在日志消息中输出有关对象的信息,从而更好地跟踪和调试程序。

在使用自动捕获’this’指针技术时,当用户使用日志记录器记录一条消息时,plog库会自动捕获当前对象的指针,并将其添加到日志消息中,以便用户在查看日志时能够识别与对象相关的消息,并更好地理解程序的行为和状态。

自动捕获’this’指针技术可以帮助用户更好地跟踪和调试程序,尤其是在多线程环境下或对象较多的复杂程序中。同时,由于自动捕获’this’指针是自动完成的,因此可以减少用户在代码中插入日志记录语句的工作量,提高开发效率。

需要注意的是,自动捕获’this’指针只在支持C++11的编译器中受支持,而且只有在MSVC编译器下才能进行自动捕获。在其他编译器或平台下,用户需要手动指定对象指针并将其添加到日志消息中。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

真的,MyBatis 核心源码入门看这个就够了(四)

4 SQL执行 再次回到demo的示例代码&#xff0c; org.junit.jupiter.api.Testvoid queryBySn() throws IOException {//1 读取配置文件InputStream in Resources.getResourceAsStream("mybatis-config.xml");//2 加载解析配置文件并获取SqlSessionFactory对象SqlSes…

华为OD机试模拟题 用 C++ 实现 - 寻找连续区间(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明寻找连续区间题目输入输出示例一输入输出说明示例二输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率…

华为OD机试题,用 Java 解【求解连续数列】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…

大数据算法自检

1 大数据亚线性空间算法 1.1 流模型的计数问题 问题定义&#xff1f;用什么算法&#xff1f;算法步骤&#xff1f;(提示&#xff1a;三层递进) 切比雪夫不等式&#xff1f;怎么证明&#xff1f;期望&#xff0c;方差&#xff0c;空间复杂度&#xff1f; 极其有限的空间存储极…

数据结构与算法(六):图结构

图是一种比线性表和树更复杂的数据结构&#xff0c;在图中&#xff0c;结点之间的关系是任意的&#xff0c;任意两个数据元素之间都可能相关。图是一种多对多的数据结构。 一、基本概念 图&#xff08;Graph&#xff09;是由顶点的有穷非空集合和顶点之间边的集合组成&#x…

每日分享(免登录积分商城系统 动力商城 兑换商城源码)

​demo软件园每日更新资源,请看到最后就能获取你想要的: 1.Python教程2022&#xff1a;100天从新手到大师 完整版 Python 100天从新手到大师是一个Python入门教程&#xff0c;Python从入门到精通&#xff0c;专门为热爱python的新手量身定做的学习计划&#xff0c;100天速成pyt…

OOM的俩种情况---主动kill/被动kill

出现OOM, 有两种处理方式&#xff1a;1. 主动Kill; 2. 被动Kill 例&#xff1a;HBase Region Server OOM定位问题复盘 现象 在HBase资源隔离项目中&#xff0c;对测试集群进行压测时&#xff0c;发现region server会出现崩溃的情况&#xff0c;单机请求量从>200到~50每秒都…

【Git使用教程】从入门到学废

文章目录1. 基础git流程图常用命令基本配置快捷指令解决GitBash乱码获取本地仓库基础操作指令查看修改的状态&#xff08;status&#xff09;添加工作区到暂存区(add)提交暂存区到本地仓库(commit)查看提交日志(log)版本回退添加文件至忽略列表总结2. 分支查看本地分支创建本地…

程序员多赚20k的接私活必备网站

为什么都是程序员&#xff0c;就有人能多赚20k&#xff1f;那是因为副业搞得那么溜啊&#xff01; 今天分享一些程序员搞钱必备的接私活网站&#xff0c;让更多程序员们在工作之余能有另外一份收入。 1.程序员客栈&#xff1a;http://proginn.com 专为程序员服务的软件外包对…

超级品牌符号怎么设计?大咖有方法

怎么设计超级LOGO图标&#xff1f;有方法&#xff01; LOGO设计大趋势&#xff1a;卡通化、拟人化 抽象符号已经泛滥 但卡通形象也已经泛滥 趣讲大白话&#xff1a;设计容易出名难 【安志强趣讲信息科技89期】 ******************************* 别以为设计一个卡通就牛X闪闪 比…

React Native使用echart——wrn-echarts

这里写自定义目录标题前言Tips详细使用过程如下1、开发环境搭建2、准备RN工程3、build App包4、 安装相关依赖5、试用Skia模式6、试用Svg模式7、封装Chart组件8、多个图表使用总结前言 平时写图表相关需求&#xff0c;用得最多的图表库就是echarts。echarts在web端的表现已经相…

机器学习:基于朴素贝叶斯对花瓣花萼的宽度和长度分类预测

机器学习&#xff1a;基于朴素贝叶斯对花瓣花萼的宽度和长度分类预测 作者&#xff1a;AOAIYI 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;AOAIYI首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞…

毕业设计 基于51单片机环境监测设计 光照 PM2.5粉尘 温湿度 2.4G无线通信

基于51单片机环境监测设计 光照 PM2.5粉尘 温湿度 2.4G无线通信1、项目简介1.1 系统构成1.2 系统功能2、部分电路设计2.1 STC89C52单片机核心系统电路设计2.2 dht11温湿度检测电路设计2.3 NRF24L01无线通信电路设计3、部分代码展示3.1 NRF24L01初始化3.2 NRF24L01的SPI写时序3.…

【数据库】数据库基本概念和类型

一、数据库基本概念 1、数据 所谓数据&#xff08;Data&#xff09;是指对客观事物进行描述并可以鉴别的符号&#xff0c;这些符号是可识别的、抽象的。它不仅仅指狭义上的数字&#xff0c;而是有多种表现形式&#xff1a;字母、文字、文本、图形、音频、视频等。现在…

STM32开发(16)----CubeMX配置DMA

CubeMX配置DMA前言一、什么是DMA&#xff1f;二、实验过程1.CubeMX配置2.代码实现3.实验结果总结前言 本章介绍使用STM32CubeMX对DMA进行配置的方法&#xff0c;DMA的原理、概念和特点&#xff0c;配置各个步骤的功能&#xff0c;并通过串口DMA传输实验方式验证。 一、什么是…

【学习笔记汇总】Github Note

本科毕业设计 Internet of Things environmental monitoring system based on STM32 STM32系列单片机工程模板 【STM32F103_Libary】基于STM32F103开发板的工程模板 ST7735屏幕【STM32F103Template】基于STM32F103开发板的工程模板 ILI9341屏幕【STM32F103_LibaryFinalVersio…

服务拆分及远程调用

目录 服务拆分 服务拆分注意事项 服务间调用 步骤一&#xff1a;注册RestTemplate 步骤二&#xff1a;修改业务层代码 总结&#xff1a; 提供者和消费者 思考 服务调用关系 服务拆分 服务拆分注意事项 单一职责&#xff1a;不同微服务&#xff0c;不要重复开发相同业…

电压放大器和电流放大器的区别是什么意思

在日常电子实验测试中&#xff0c;很多电子工程师都会使用到电压放大器和电流放大器&#xff0c;但是很多新手工程师却无法区分两者的区别&#xff0c;下面就让安泰电子来为我们讲解电压放大器和电流放大器的区别是什么意思。 一、电压放大器介绍&#xff1a; 电压放大器是一种…

2023王道考研数据结构笔记第一章绪论

第一章 绪论 1.1 数据结构的基本概念 1.数据&#xff1a;数据是信息的载体&#xff0c;是描述客观事物属性的数、字符以及所有能输入到计算机中并被程序识别和处理的符号的集合。 2.数据元素&#xff1a;数据元素是数据的基本单位&#xff0c;通常作为一个整体进行考虑和处理…

【MySQL】数据库中锁和事务的相关知识点

1.事务的四大特点 原子性&#xff1a;事务中的所有操作要么都成功&#xff0c;要么都失败。所有的操作是一个不可分割的单位。一致性&#xff1a;一致性指的是事务执行前后&#xff0c;数据从一个合法性状态转移到另一个合法性状态。这个状态和业务有关&#xff0c;是自己定义…