C++项目实战——基于多设计模式下的同步异步日志系统-⑤-实用工具类设计

news2025/5/24 15:33:33

文章目录

  • 专栏导读
  • 获取系统时间
    • time介绍
  • getTime函数设计
  • 判断文件是否存在
    • stat介绍
    • exists函数设计
  • 获取文件所在路径
    • find_last_of介绍
    • path函数设计
  • 创建文件所在目录
    • mkdir介绍
    • find_first_of介绍
    • 函数createDirectory设计
  • 实用工具类整理

专栏导读

🌸作者简介:花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C++项目——基于多设计模式下的同步与异步日志系统

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法Linux

在这里插入图片描述
在项目中,我们时常会需要用到一些与业务无关的功能,如:获取系统时间、创建目录、获取路径等。我们将这些零碎的功能接口提前完成,以便于项目中会用到。

实用工具类主要包含以下功能:

  • 获取系统时间
  • 判断文件是否存在
  • 获取文件所在路径
  • 创建文件所在目录

获取系统时间

我们将获取系统时间的接口单独封装在一个Date类中。获取系统时间,我们可以使用库函数time来实现。

time介绍

C语言中的time函数是一个用于获取当前系统时间的标准库函数,它定义在<time.h>头文件中。time函数通常返回自1970年1月1日以来经过的秒数,这被称为Unix时间戳(或Epoch时间)。它的函数原型如下:

time_t time(time_t *tloc);
  • time_t是一种数据类型,通常是一个整数类型(如long),用来存储时间值;
  • tloc是一个指向time_t类型的指针,用于存储获取的时间值。你可以将它设置为NULL,如果你不需要获取时间值的副本;

time函数返回一个表示当前时间的时间戳,单位是。如果传递了非空的tloc指针,它还会将时间戳的副本存储在tloc指向的地址中,以便你可以稍后使用。

getTime函数设计

#include <iostream>
#include <ctime>

class Date
{
public:
    static size_t getTime()
    {
        return (size_t)time(nullptr);
    }
};

判断文件是否存在

判断文件是否存在、获取文件所在路径、创建目录这三个功能都与文件相关,因此我们将三者在一个File类中实现。

实现思路:

  • 函数参数为一个路径字符串,表示所要判断的文件的路径;
  • 函数返回值为bool类型,若该文件存在则返回true
  • 通过系统调用stat来实现;

stat介绍

认识stat函数之前我们首先认识一下struct stat类型。

在C语言中,struct stat是一个用于表示文件或文件系统对象属性的结构体类型。这个结构体通常用于与文件和目录相关的操作,例如获取文件的大小、访问权限、最后修改时间等信息。struct stat类型的定义通常由操作系统提供,因此其具体字段可能会因操作系统而异。

以下是一个典型的struct stat结构体的字段,尽管具体字段可能会因操作系统而异:

struct stat {
    dev_t     st_dev;         // 文件所在设备的ID
    ino_t     st_ino;         // 文件的inode号
    mode_t    st_mode;        // 文件的访问权限和类型
    nlink_t   st_nlink;       // 文件的硬链接数量
    uid_t     st_uid;         // 文件的所有者的用户ID
    gid_t     st_gid;         // 文件的所有者的组ID
    off_t     st_size;        // 文件的大小(以字节为单位)
    time_t    st_atime;       // 文件的最后访问时间
    time_t    st_mtime;       // 文件的最后修改时间
    time_t    st_ctime;       // 文件的最后状态改变时间
    blksize_t st_blksize;     // 文件系统I/O操作的最佳块大小
    blkcnt_t  st_blocks;      // 文件占用的块数
};

struct stat结构体中的这些字段提供了关于文件或目录的各种信息。不同的操作系统可能会提供额外的字段,或者字段的意义可能会有所不同。

stat函数用于获取与指定路径名相关联的文件或目录的属性,并将这些属性填充到一个struct stat结构体中。以下是stat函数的函数原型:

int stat(const char *pathname, struct stat *statbuf);
  • pathname是要获取属性的文件或目录的路径名;
  • statbuf是一个指向struct stat结构体的指针,用于存储获取到的属性信息;
  • stat函数返回一个整数值,如果操作成功,返回0;如果出现错误,返回-1,并设置errno全局变量以指示错误的类型。

注意需要包含头文件<sys/stat.h><unistd.h>来使用stat函数。

exists函数设计

static bool exists(const std::string &pathname)
{
    struct stat st;
    if (stat(pathname.c_str(), &st) < 0) // 打开文件失败则代表文件不存在
    {
        return false;
    }
    return true;
}

获取文件所在路径

假设存在文件“user/aaa/bbb/ccc/test.cc”,我们需要获取文件test.cc所在的路径即"user/aaa/bbb/ccc"

实现这个功能我们将会用到库函数find_last_of

find_last_of介绍

C++标准库中的find_last_of函数是用于在字符串中查找指定字符集中最后一个出现的字符,并返回其位置或索引。这个函数通常用于字符串操作,允许你在字符串中查找某些字符集的最后一个匹配字符。

函数格式如下:

size_t find_last_of(const string& str, size_t pos = string::npos) const;
size_t find_last_of(const char* s, size_t pos = string::npos) const;
size_t find_last_of(const char* s, size_t pos, size_t n) const;

其中,

  • str是要搜索的字符串;
  • s是要查找的字符集;
  • pos是可选的参数,用于指定搜索的起始位置,默认为string::npos,表示从字符串的末尾开始向前搜索。

这个函数返回匹配字符集中任何字符的最后一个位置的索引,如果未找到匹配字符,则返回string::npos。需要注意的是,返回的索引是从0开始的。

path函数设计

就以文件“user/aaa/bbb/ccc/test.cc”为例,要想获取文件路径,我们只需要找到最后一个‘/ 或者 \\所在位置,并将在这之前的内容全部返回即可。若不存在路径分隔符/或者 \\,则证明该文件在当前目录,返回. 即可。

static std::string path(const std::string &pathname)
{
    size_t pos = pathname.find_last_of("/\\");
    if (pos == std::string::npos)
        return ".";
    return pathname.substr(0, pos + 1);
}

创建文件所在目录

以文件路径'' user/aaa/bbb/ccc/test.cc '',给函数传递该路径字符串,函数的任务是依次创建目录useraaabbbccc

需要注意的小细节是,每次要创建一个目录时,都要判断该目录是否存在,使用之前实现的exists函数即可。

我们依靠系统调用mkdir来完成目录的创建,首先来认识一下mkdir

mkdir介绍

mkdir 函数是一个系统调用,用于在文件系统中创建新的目录(文件夹)。它通常用于在文件系统中创建一个新的目录,以便存储文件或其他目录。

函数原型如下:

#include <sys/stat.h>
#include <sys/types.h>

int mkdir(const char *pathname, mode_t mode);
  • pathname 是一个字符串,表示要创建的目录的路径。这个路径可以是相对路径绝对路径

  • mode 是一个权限掩码,用于指定新目录的权限。这个权限掩码通常是八进制数;

mkdir 函数的功能是创建一个新的目录,并根据指定的权限设置来设置目录的权限。如果成功创建目录,函数将返回0,否则返回-1,并设置 errno 变量以指示错误的原因。

find_first_of介绍

在 C++ 中,find_first_of 是字符串(std::string)和其他序列容器中的成员函数,用于在目标字符串中查找第一个匹配源字符串中任何字符的位置。它的功能是找到目标字符串中的任何一个字符在源字符串中第一次出现的位置。

函数类型如下:

size_t find_first_of(const std::basic_string& str, size_t pos = 0) const;
size_t find_first_of(const CharT* s, size_t pos = 0) const;
size_t find_first_of(const CharT* s, size_t pos, size_t n) const;
size_t find_first_of(CharT ch, size_t pos = 0) const;
  • str:一个字符串,表示源字符串,函数将在目标字符串中查找源字符串中的任何字符;
  • s:一个字符数组或 C 字符串,表示源字符序列,函数将在目标字符串中查找数组中的任何字符;
  • ch:一个字符,表示要查找的字符;
  • pos:可选参数,表示开始查找的位置。默认为0,即从字符串的开头开始查找;
  • n:可选参数,与 s 一起使用,表示要查找的字符数量;

find_first_of 函数返回目标字符串中第一个匹配源字符序列中任何字符的位置(索引),如果没有找到匹配的字符,则返回 std::string::npos

函数createDirectory设计

static void createDirectory(const std::string pathname)
{
    size_t pos = 0, idx = 0;
    while(idx < pathname.size())
    {
        pos = pathname.find_first_of("/\\", idx);
        if(pos == std::string::npos)
        {
            mkdir(pathname.c_str(), 0777);
        }
        std::string parent_dir = pathname.substr(0, pos + 1);
        if(exists(parent_dir) == true) // 判断该文件是否已经存在
        {
            idx = pos + 1;
            continue;
        }
        mkdir(parent_dir.c_str(), 0777);
        idx = pos + 1;
    }
}

实用工具类整理

在项目实现中,我们最好使用自己的命名空间。我们将各个类整体放入LOG(名称自行决定)命名空间中的util命名空间中。

#ifndef __M_UTIL_H__
#define __M_UTIL_H__

/* 
    使用工具类实现:
    1. 获取系统时间
    2. 判断文件是否存在
    3. 获取文件所在路径
    4. 创建文件所在目录
*/

#include <iostream>
#include <ctime>
#include <sys/stat.h>

namespace LOG
{
    namespace util
    {
        class Date
        {
        public:
            static size_t getTime()
            {
                return (size_t)time(nullptr);
            }
        };
       
        class File
        {
        public:
            static bool exists(const std::string &pathname)
            {
                struct stat st;
                if (stat(pathname.c_str(), &st) < 0) // 打开文件失败则代表文件不存在
                {
                    return false;
                }
                return true;
            }

            static std::string path(const std::string &pathname)
            {
                size_t pos = pathname.find_last_of("/\\");
                if (pos == std::string::npos)
                    return ".";
                return pathname.substr(0, pos + 1);
            }

            static void createDirectory(const std::string pathname)
            {
                size_t pos = 0, idx = 0;
                while(idx < pathname.size())
                {
                    pos = pathname.find_first_of("/\\", idx);
                    if(pos == std::string::npos)
                    {
                        mkdir(pathname.c_str(), 0777);
                    }
                    std::string parent_dir = pathname.substr(0, pos + 1); // 判断该文件是否已经存在
                    if(exists(parent_dir) == true)
                    {
                        idx = pos + 1;
                        continue;
                    }
                    mkdir(parent_dir.c_str(), 0777);
                    idx = pos + 1;
                }
            }
        };
    }
}
#endif

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据的真正价值是数据要素市场化开发

随着人工智能、互联网、物联网、大数据、云计算、区块链等新一代信息化、数字化技术的应用&#xff0c;各行各业都开始了新一轮的产业革命和转型升级。在这个过程中&#xff0c;数据伴随着信息化、数字化的推进越发变得重要&#xff0c;到了2020年直接成为了继土地、劳动力、资…

人工智能AI 全栈体系(三)

第一章 神经网络是如何实现的 一个神经网络用不同的数据做训练&#xff0c;就可以识别不同的东西&#xff0c;那么神经网络究竟是怎么训练的&#xff1f; 三、神经网络是如何训练的&#xff1f; 1. 小朋友如何认识小动物&#xff1f; 小时候&#xff0c;每当看到一个小动物时…

R3LIVE源码解析(10) — R3LIVE中r3live_vio.cpp文件

目录 1 r3live_vio.cpp简介 2 r3live_vio.cpp源码解析 1 r3live_vio.cpp简介 R3LIVE主要的公式推导在VIO上&#xff0c;所以我们来细细的分析这部分的功能。R3LIVE将VIO分成了两步&#xff0c;一是直接通过帧间的光流来追踪地图点&#xff0c;并且通过最小化追踪到的地图点的…

Springboot部署服务器项目上线

第一步&#xff0c;项目打包&#xff0c;有两种方式 第一种、直接在项目根目录打开终端&#xff0c;输入以下语句即可。如下图&#xff1a; mvn clean package -DskipTests 第二种、在右侧点击 Maven选项&#xff0c;选择鼠标左键双击package选项即可。如下图&#xff1a; 两…

《研发效能(DevOps)工程师国家职业技术认证》工信部教考中心认证证书:塑造研发效能的黄金标准丨IDCF

随着科技的飞速发展和市场竞争的日益激烈&#xff0c;高素质的技术管理人才在当今社会中扮演着越来越重要的角色。特别是在信息技术领域&#xff0c;企业对于拥有专业技能和丰富知识的研发效能管理与技术人才的需求愈发旺盛。工业和信息化部教育与考试中心&#xff08;以下简称…

ueditor百度富文本编辑器粘贴后html丢失class和style样式

问题 项目经理从123在线编辑上排版好的文章&#xff0c;粘贴到项目的编辑器上&#xff0c;样式完全乱了, 排版是这样的&#xff1a; 复制到ueditor后的格式&#xff1a; 这天差地别呀&#xff0c;于是打开代码模式&#xff0c;发现section的属性全没了 但是&#xff0c;sp…

如何规划好自己的工作与学习时间?助你提高办事效率的待办提醒软件

在竞争激烈的职场中&#xff0c;想要脱颖而出、不断提升自我价值&#xff0c;我们必须不断学习。然而&#xff0c;很多上班族都发现工作忙碌&#xff0c;根本没有时间专注于学习。那么&#xff0c;如何规划好工作与学习时间呢&#xff1f;每个人的时间都是有限的&#xff0c;因…

Transformer最直观的解析(译)

在这篇文章中&#xff0c;我们将看看“Transformer”——一个利用注意力机制来提高模型训练速度的模型。Transformer在特定任务中优于谷歌神经机器翻译模型。然而&#xff0c;最大的好处来自于Transformer如何使自己适合并行化。事实上&#xff0c;Google Cloud推荐使用The Tra…

STM32F4的USB Host驱动移植详细步骤及问题解决

文章目录 1、库文件准备2、工程准备3、移植3.1、新建USB相关文件夹3.2、加USB相关代码3.3、添加头文件路径 4、修改相关代码1、修改usbh_usr.c①&#xff0c;usb_conf.h&#xff0c;include部分&#xff0c;②&#xff0c;定义全局宏③&#xff0c;修改usbh_usr.c 2、修改diski…

iis建立站点外网无法访问(防火墙的入站规则和出站)

iis建立站点 外网无法访问 原因&#xff1a; 被防火墙拦截了 处理方式&#xff1a; 打开window防火墙--高级设置--入站 出站就是你访问外网&#xff0c;入站就是外网访问你&#xff0c;用户可以创建入站和出站规则&#xff0c;从而阻挡或者允许特定程序或者端口进行连接; 可以使…

每日一博 - 图解进程(Process)和线程(Thread)区别联系

文章目录 概述图解小结 概述 进程&#xff08;Process&#xff09;和线程&#xff08;Thread&#xff09;是操作系统中管理和执行任务的两个基本概念&#xff0c;它们之间有以下主要区别&#xff1a; 独立性&#xff1a; 进程是独立的执行单位。每个进程有自己的独立地址空间、…

Nginx神奇的499竟然不在HTTP响应码标准内?快来了解一下!

1 前言 高性能的HTTP和反向代理服务器&#xff0c;Nginx用来&#xff1a; 搭建Web Server作负载均衡供配置的日志字段丰富&#xff0c;从各类HTTP头部到内部性能数据都有 Nginx的访问日志中&#xff0c;存在499状态码的日志。但常见4xx状态码只有400、401、403、404等&#…

【数据结构】二叉树的链式结构

【数据结构】二叉树的链式存储结构 二叉树的存储结构 typedef int BTDataType; // 二叉树的结构 typedef struct BinaryTreeNode {BTDataType data; // 树的值struct BinaryTreeNode *left; // 左孩子struct BinaryTreeNode *right;// 右孩子 } BinaryTreeNode;二…

【数据结构】TOP-K问题/使用堆解决

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

第70步 时间序列建模实战:ARIMA建模(JMP)

基于WIN10的64位系统演示 一、写在前面 这一期&#xff0c;我们使用JMP进行SARIMA模型的构建。 同样&#xff0c;这里使用这个数据&#xff1a; 《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with …

flutter简单的本地草稿箱功能

需求1&#xff1a;发帖退出时提示是否保存草稿 需求2&#xff1a;每条草稿中可以保存多张图片(最多9张)或一条视频及三十来个其它参数 需求3&#xff1a;每条草稿都是可以被覆盖的、可以点击删除 需求4&#xff1a;草稿页面可以一键清空 需求5&#xff1a;草稿随app删除一起没掉…

简单2D几何求交点

2D图形SVG工具添加了通过选项属性显示交点的功能。 PaladinDu&#xff1a;2D图形SVG化工具0 赞同 0 评论文章 在这个工具中&#xff0c;已经定义的数据结构有点&#xff0c;线段&#xff0c;有向线段&#xff0c;射线&#xff0c;直线&#xff0c;多边形&#xff0c;和圆。 …

【技巧】如何保护PDF文件不被随意修改?

做好的PDF文件&#xff0c;不想被他人随意修改&#xff0c;只要给PDF设置“限制保护”就可以了&#xff0c;设置保护后需要输入密码才能进行编辑。 设置“限制保护”我们需要用到PDF编辑器&#xff0c;以小编使用的编辑器为例&#xff0c;首先通过编辑器打开PDF文件后&#xf…

医学访问学者申请四点规划建议

医学领域一直以来都是人类社会的重要组成部分&#xff0c;而作为一名有志于成为一名医学领域的访问学者&#xff0c;您需要明确自己的目标并做好充分准备。知识人网小编将为您提供四点规划建议&#xff0c;以帮助您成功申请医学访问学者的机会。 第一点&#xff1a;明确研究方向…

input 的 placeholder 样式

::placeholder 伪元素 这个伪元素可以改变 input、textarea 占位文本的样式。 input::placeholder {color: green; }完整的兼容性写法&#xff1a; input {&::-webkit-input-placeholder, /* WebKit browsers*/ &:-moz-input-placeholder, /* Mozilla Firefox 4 to …