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

文章目录

  • 专栏导读
  • 获取系统时间
    • 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;         // 文件所在设备的IDino_t     st_ino;         // 文件的inode号mode_t    st_mode;        // 文件的访问权限和类型nlink_t   st_nlink;       // 文件的硬链接数量uid_t     st_uid;         // 文件的所有者的用户IDgid_t     st_gid;         // 文件的所有者的组IDoff_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.hqwc.cn/news/108785.html

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

相关文章

图论第三天|130. 被围绕的区域、417. 太平洋大西洋水流问题、827. 最大人工岛

130. 被围绕的区域 文档讲解 &#xff1a;代码随想录 - 130. 被围绕的区域 状态&#xff1a;开始学习。 思路&#xff1a; 步骤一&#xff1a; 深搜或者广搜将地图周边的 ‘O’ 全部改成 ’A’&#xff0c;如图所示&#xff1a; 步骤二&#xff1a; 再遍历地图&#xff0c;将 …

(3)MyBatis-Plus待开发

常用注解 TableName MyBatis-Plus在确定操作的表时&#xff0c;由BaseMapper的泛型决定即实体类型决定&#xff0c;且默认操作的表名和实体类型的类名一致,如果不一致则会因找不到表报异常 //向表中插入一条数据 Test public void testInsert(){User user new User(null, &…

基因型数据VCF转EXCEL亲测好用

import pandas as pd df pd.read_csv(shuju.vcf, sep\t, comment#, headerNone,encodingutf-8) df.to_excel(outputFile2.xlsx, indexFalse,encodingutf-8) 以上就是转成功的截图&#xff0c;需要注意的是一定要写入编码方式&#xff0c;UTF-8 &#xff0c;第一次我没有写编码…

Zabbix“专家坐诊”第203期问答汇总

问题一 Q&#xff1a;用的模板&#xff0c;没用创建动作&#xff0c;但是触发器触发了我钉钉直接被通知了&#xff0c;怎么取消模板自带的动作&#xff1f; A&#xff1a;没有动作是不会触发事件告警的 &#xff0c;确定是从这个平台推出的钉钉消息&#xff1f;或者看下zabbix…

论文解读 | 用于3D对象检测的PV-RCNN网络原创

原创 | 文 BFT机器人 01 背景 本文的背景涉及到3D物体检测&#xff0c;这是一个在自动驾驶和机器人等领域应用广泛的重要问题。在这些领域&#xff0c;LiDAR传感器被广泛用于捕捉3D场景信息&#xff0c;生成不规则且稀疏的点云数据。这些点云数据提供了理解和感知3D场景的关键…

数据可视化大屏模板 | 保姆级使用教程

近来很多朋友私信咨询怎么下载使用数据可视化大屏模板&#xff0c;在这里就给大家做一个相对简单的教程总结。有需要的朋友记得先收藏保存&#xff0c;以便不时之需。 数据可视化大屏制作软件&#xff1a;奥威BI系统 数据可视化报表模板板块&#xff1a;模板秀 主要操作&…

Linux 修改SSH的显示样式,修改终端shell显示的样式,美观更改

要修改SSH的显示样式&#xff0c;您可以使用自定义的PS1&#xff08;提示字符串1&#xff09;变量来更改命令行提示符的外观。在您的情况下&#xff0c;您想要的格式似乎包括日期和时间&#xff0c;以及当前目录。以下是一个示例PS1设置&#xff0c;可以实现您所描述的样式&…

【Seata】04 - Seata TCC 模式 Demo 调用流程分析

文章目录 前言参考目录版本说明前置知识1、TCC 模式预留资源2、TCC 模式可能会出现的问题2.1、幂等性问题2.2、空回滚问题2.3、悬挂问题 测试 Demo1、数据库表结构2、模块说明3、调用逻辑说明4、分析流程说明 Seata TCC 模式 Commit 调用流程1、调用流程图2、TCC 动作拦截器&am…

格式化以后数据还在吗 格式化后数据怎么恢复

格式化是一种保护数据存储设备、清空部分不使用文件的操作方法&#xff0c;它能够对数据存储设备中的文件进行初始化。 但是如果格式化时不小心清空了重要的数据&#xff0c;可能会造成数据丢失的问题。今天&#xff0c;我将以格式化以后数据还在吗&#xff0c;格式化后数据怎么…

第三方电容笔怎么样?开学季平价电容笔排行榜

苹果的电容笔能得到那么多人的认可&#xff0c;主要还是得益于这款电容笔的出色性能&#xff0c;以及它特有的“重力压感”这个特有功能。不过苹果的原装电容笔&#xff0c;价格也不便宜&#xff0c;大部分人还是用了平价的平替电容笔。现在很多人都喜欢用ipad来画画或者做记录…

【C#-1】C#调用matlab生成的dll库

matlab打包dll 1、matlab示例程序&#xff1a; function untitled4(x)z peaks(x);figuresurf(z) end 2、输入deploytool打包matlab程序&#xff0c;具体如下&#xff1a; 3、拷贝 打包成功后&#xff0c;将生成for_redistribution_files_only文件夹中的dll文件拷贝到C#程序…

关于HTTP协议的概述

HTTP 的报文大概分为三大部分。第一部分是请求行&#xff0c;第二部分是请求的首部&#xff0c;第三部分才是请求的正文实体。 POST 往往是用来创建一个资源的&#xff0c;而 PUT 往往是用来修改一个资源的。 Accept-Charset&#xff0c;表示客户端可以接受的字符集。防止传过…