在开发大型自动化系统或者多线程应用时,日志记录和时间追踪通常是系统调试和性能优化的关键部分。CAuxiliary
类是一个封装了文件日志记录和高精度计时功能的实用工具类,旨在为开发人员提供一种简便的方式,来实现系统运行的日志记录和时间性能分析。本文将详细介绍如何使用 CAuxiliary
类来记录日志和进行高精度的时间测量。
头文件
#pragma once
#include <chrono> // std::chrono
class CAuxiliary
{
public:
CAuxiliary() : mIsRecord(false) {}
~CAuxiliary() { CloseFile(); }
// 设置是否记录日志
bool CreateAndOpenFile(CString fileName, bool IsRecord);
void CloseFile();
void AppendContent(CString content);
// 插入开始时间,当bFirstBegin为true时表示首次开始
void StartTime(bool bFirstBegin = false);
// 插入结束时间,当bAllEnd为true时表示全部结束,这是将会记录总时间
void EndTime(CString content, bool bAllEnd = false);
private:
CStdioFile m_sf;
bool mIsRecord;
// 用于高精度计时
std::chrono::high_resolution_clock::time_point m_start;
std::chrono::high_resolution_clock::time_point m_firstBegin;
std::chrono::high_resolution_clock::time_point m_end;
std::chrono::high_resolution_clock::time_point m_mediu;
};
源文件
#include "stdafx.h" // 适用于 MFC 项目,包含标准的 MFC 头文件
#include <iostream>
#include <chrono> // std::chrono
#include <fstream>
#include"CAuxiliary.h"
using namespace std;
bool CAuxiliary::CreateAndOpenFile(CString fileName, bool IsRecord)
{
mIsRecord = IsRecord;
if (!mIsRecord) { return true; }
// 如果文件已经打开,先关闭它
if (m_sf.m_hFile != CFile::hFileNull) {
CloseFile();
}
// 尝试打开文件
if (m_sf.Open(fileName, CFile::modeCreate | CFile::modeWrite)) {
return true;
}
return false;
}
void CAuxiliary::CloseFile()
{
if (!mIsRecord) { return; }
if (m_sf.m_hFile != CFile::hFileNull) {
m_sf.Close();
}
}
void CAuxiliary::AppendContent(CString content)
{
if (!mIsRecord) { return; }
if (m_sf.m_hFile == CFile::hFileNull) { return; }
// 计算当前时间差(以毫秒为单位)
auto now = std::chrono::high_resolution_clock::now();
std::chrono::duration<int64_t, std::milli> duration = std::chrono::duration_cast<std::chrono::duration<int64_t, std::milli>>(now - m_mediu);
m_mediu = now;
// 获取当前时间(时:分:秒:毫秒)
SYSTEMTIME st;
GetLocalTime(&st); // 获取本地时间
// 格式化时间戳
int ms = static_cast<int>(duration.count()); // 转换为毫秒
CString timeStamp;
timeStamp.Format(_T("%02d:%02d:%02d:%03d\t%dms\t%s\n"),
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, ms, content);
m_sf.SeekToEnd();
m_sf.WriteString(timeStamp);
}
void CAuxiliary::StartTime(bool bFirstBegin)
{
if (!mIsRecord) { return; }
m_start = std::chrono::high_resolution_clock::now();
m_mediu = m_start;
if (bFirstBegin) {
m_firstBegin = m_start;
}
}
void CAuxiliary::EndTime(CString content, bool bAllEnd)
{
if (!mIsRecord) { return; }
if (m_sf.m_hFile == CFile::hFileNull) { return; }
m_end = std::chrono::high_resolution_clock::now();
// 计算时间差(以毫秒为单位)
std::chrono::duration<int64_t, std::milli> duration = bAllEnd ? std::chrono::duration_cast<std::chrono::duration<int64_t, std::milli>>(m_end - m_firstBegin)
: std::chrono::duration_cast<std::chrono::duration<int64_t, std::milli>>(m_end - m_start);
int ms = static_cast<int>(duration.count()); // 转换为毫秒
CString result;
result.Format(_T("%s:\t%dms\n"), content, ms);
m_sf.SeekToEnd();
m_sf.WriteString(result);
}
类的设计与功能
CAuxiliary
类设计上非常简洁,主要实现了以下功能:
- 日志记录: 该类可以创建一个日志文件,并在文件中附加内容。
- 高精度计时: 使用
std::chrono
提供的高精度计时器来记录时间,适合记录程序的执行时间。 - 开始和结束时间记录: 通过设置开始时间和结束时间,可以计算程序执行的时长,支持记录部分执行时间和总体执行时间。
类的成员函数解析
1. CreateAndOpenFile
bool CAuxiliary::CreateAndOpenFile(CString fileName, bool IsRecord)
此函数用于创建并打开日志文件。如果 IsRecord
为 true
,它将打开指定路径的日志文件。如果文件已存在,则会先关闭再重新打开文件。否则,如果 IsRecord
为 false
,该函数将直接返回 true
,而不执行文件操作。
使用示例:
CAuxiliary aux;
aux.CreateAndOpenFile(_T("log.txt"), true);
2. CloseFile
void CAuxiliary::CloseFile()
该函数用于关闭打开的日志文件。当不再需要记录日志时,可以调用此函数释放资源。文件会在不再记录日志时被关闭。
使用示例:
aux.CloseFile();
3. AppendContent
void CAuxiliary::AppendContent(CString content)
此函数用于向日志文件中追加内容。它会在内容前加上当前时间戳(包括小时、分钟、秒和毫秒)以及从上次调用 AppendContent
以来的时间差(以毫秒为单位)。如果没有开启记录日志功能,函数不会执行任何操作。
使用示例:
aux.AppendContent(_T("Processing step 1"));
4. StartTime
void CAuxiliary::StartTime(bool bFirstBegin)
此函数用于记录操作的开始时间。如果 bFirstBegin
为 true
,则会记录首次开始时间。此时间点将作为后续计算时间差的基准。
使用示例:
aux.StartTime(true);
5. EndTime
void CAuxiliary::EndTime(CString content, bool bAllEnd)
此函数用于记录操作的结束时间并计算与开始时间的差值。它支持两种模式:
- 部分结束模式(默认):计算从
StartTime
到EndTime
的时间差。 - 全部结束模式:计算从首次开始时间(即
StartTime(true)
)到当前结束时间的时间差。这个功能对于记录整个任务的总耗时非常有用。
使用示例:
aux.EndTime(_T("Processing step 1 finished"));
示例代码
下面是一个完整的示例,展示了如何使用 CAuxiliary
类来记录日志并进行时间测量:
#include "CAuxiliary.h"
#include <thread>
int main() {
CAuxiliary aux;
// 创建并打开日志文件
if (aux.CreateAndOpenFile(_T("process_log.txt"), true)) {
// 开始时间记录
aux.StartTime(true);
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟延迟
//阶段一
aux.StartTime();
aux.AppendContent(_T("Start processing step 1"));// 模拟处理步骤
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟延迟
aux.EndTime(_T("Processing step 1 finished")); // 阶段一结束时间记录
//阶段二
aux.StartTime();
aux.AppendContent(_T("Start processing step 2")); // 模拟处理步骤
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟延迟
aux.EndTime(_T("Processing step 2 finished"));// 阶段二结束时间记录
aux.EndTime(_T("Process finished"),true);//总的时间
aux.CloseFile(); // 关闭文件
}
return 0;
}