C++编程之自定义日志类 ——log4cpp使用详解

log4cpp简介与安装

log4cpp是一个开源的C++日志管理库,可以通过它来记录程序运行过程中产生的各种信息。也可以进行再包装实现个人自定义的日志类。

log4cpp安装
  1. 下载:
    wget https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz
  2. 解包
    tar zxvf log4cpp-1.1.3.tar.gz
  3. cd log4cpp
  4. ./configure --with-pthreads
  5. ./configure
  6. make
  7. make install
  8. 添加环境变量
    vim /etc/profile.d/log4cpp.sh
    在文件中添加:
    LD_LIBRARY_PATH=:$LD_LIBRARY_PATH:/usr/local/lib export LD_LIBRARY_PATH
    修改文件权限
    chmod a+x /etc/profile.d/log4cpp.sh
  9. ldconfig -v

安装好后, 在编译源码文件时要加上-llog4cpp -lpthread来链接动态库

log4cpp简单介绍

log4cpp库中主要分为三大类:Category(种类)、Appender(附加目的地)和Layout(布局)。

  • category类是日志记录的主要执行类,它负责写日志
  • appender类用来指明目的地,即日志要写到什么地方去
  • layout类指明日志输出的格式

应用时的大致流程:

  1. 定义一个layout类对象,确定输出日志信息的格式
  2. 定义一个appender类对象,确定日志输出到什么地方,然后把layout对象用setlayout方法绑定一下。
  3. 定义一个catergory对象,与appender类对象绑定
  4. 调用catergory对象进行写日志

简单示例

#include <iostream>
#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/BasicLayout.hh>

int main()
{
   
	//1. 初始化一个layout对象
  log4cpp::Layout* layout =  new log4cpp::BasicLayout();
   // 2. 初始化一个appender 对象
  log4cpp::Appender* appender = new log4cpp::FileAppender("FileAppender","./test_log4cpp1.log");
    // 3. 把layout对象附着在appender对象上
  appender->setLayout(layout);
  // 4. 实例化一个category对象
  log4cpp::Category& warn_log = log4cpp::Category::getInstance("mywarn");
  // 5. 把appender对象附到category上
  warn_log.setAppender(appender);
  // 6. 设置category的优先级,低于此优先级的日志不被记录
  warn_log.setPriority(log4cpp::Priority::WARN);
  // 记录一些日志
  warn_log.info("Program info which cannot be wirten");
  warn_log.debug("This debug message will fail to write");
  warn_log.alert("Alert info");
  // 其他记录日志方式
  warn_log.log(log4cpp::Priority::WARN, "This will be a logged warning");
  log4cpp::Priority::PriorityLevel priority;
  bool this_is_critical = true;
  if(this_is_critical)
  {
   
       priority = log4cpp::Priority::CRIT;
  }
  else
  {
   
       priority = log4cpp::Priority::DEBUG;
  }
  warn_log.log(priority,"Importance depends on context");
        
  // 清理所有资源
  log4cpp::Category::shutdown();
  return 0;
}

可以看到整套流程下来还是有点复杂的,可以在后续包装成一个自定义的日志类进行日志记录。

layout布局——日志输出格式

layout对象规定了日志输出的内容格式,创建后需要和appender对象绑定生效。
需要注意的是,一个布局对象只能绑定一个appender对象。
比较常用的布局有两种:log4cpp::BasicLayoutlog4cpp::PatternLayout

log4cpp::BasicLayout

log4cpp::BasicLayout是最简单的布局,输出时间戳ÿ

  • 16
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C++ 中,我们可以使用串口来进行串口通信。这里我们将自定义一个串口,以便更好地理解串口通信的原理和实现。 首先,我们需要引入一些头文件: ```c++ #include <windows.h> #include <iostream> ``` 接着,我们定义一个串口,其中包含了串口的打开、关闭、读取和写入等操作: ```c++ class SerialPort { public: SerialPort(); ~SerialPort(); bool Open(int portNo, int baudRate); bool Close(); int ReadData(char *buffer, unsigned int nbChar); bool WriteData(char *buffer, unsigned int nbChar); bool IsOpened() const; private: HANDLE m_hComm; bool m_bOpened; }; ``` 其中,m_hComm 是串口的句柄,m_bOpened 表示串口是否打开。 接下来,我们来实现这些操作。 首先是串口的打开操作: ```c++ bool SerialPort::Open(int portNo, int baudRate) { if (m_bOpened) { Close(); } char portName[50]; sprintf_s(portName, "\\\\.\\COM%d", portNo); m_hComm = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); if (m_hComm == INVALID_HANDLE_VALUE) { std::cerr << "Failed to open serial port!\n"; return false; } DCB dcb; GetCommState(m_hComm, &dcb); dcb.BaudRate = baudRate; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(m_hComm, &dcb)) { std::cerr << "Failed to set serial port parameters!\n"; CloseHandle(m_hComm); return false; } m_bOpened = true; return true; } ``` 这里我们首先判断串口是否已经打开,如果已经打开则先关闭,然后根据串口号构建串口名称,并使用 CreateFile 函数打开串口。接着,我们设置串口的参数,包括波特率、数据位、校验位和停止位等。如果设置成功,则将 m_bOpened 设置为 true 并返回 true,否则返回 false。 接下来是串口的关闭操作: ```c++ bool SerialPort::Close() { if (!m_bOpened) { return true; } if (CloseHandle(m_hComm)) { m_bOpened = false; return true; } return false; } ``` 这里我们只需要调用 CloseHandle 函数关闭串口,并将 m_bOpened 设置为 false 即可。 接下来是串口的读取操作: ```c++ int SerialPort::ReadData(char *buffer, unsigned int nbChar) { DWORD bytesRead; if (!ReadFile(m_hComm, buffer, nbChar, &bytesRead, nullptr)) { std::cerr << "Failed to read data from serial port!\n"; return -1; } return bytesRead; } ``` 这里我们使用 ReadFile 函数从串口读取数据,并将读取的字节数存储在 bytesRead 变量中,并返回 bytesRead。 最后是串口的写入操作: ```c++ bool SerialPort::WriteData(char *buffer, unsigned int nbChar) { DWORD bytesSent; if (!WriteFile(m_hComm, buffer, nbChar, &bytesSent, nullptr)) { std::cerr << "Failed to write data to serial port!\n"; return false; } return true; } ``` 这里我们使用 WriteFile 函数将数据写入串口,并返回写入是否成功的结果。 最后,我们来实现一个判断串口是否打开的函数: ```c++ bool SerialPort::IsOpened() const { return m_bOpened; } ``` 这里只需要返回 m_bOpened 即可。 至此,我们就完成了一个简单的自定义串口。可以通过实例化这个来进行串口通信的操作,具体使用方法可以参考下面的示例代码: ```c++ int main() { SerialPort port; if (!port.Open(1, 9600)) { return -1; } char buffer[1024]; while (true) { int bytesRead = port.ReadData(buffer, sizeof(buffer)); if (bytesRead > 0) { buffer[bytesRead] = '\0'; std::cout << buffer << std::endl; } } port.Close(); return 0; } ``` 在这个示例中,我们首先实例化了一个 SerialPort ,并通过 Open 函数打开了 COM1 号串口。然后,我们通过 ReadData 函数从串口读取数据,并将读取的数据打印到控制台上。最后,我们通过 Close 函数关闭了串口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值