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.mzph.cn/news/81018.shtml

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

相关文章

VS code 下 makefile 【缺少分隔符 停下来】 报错解决方法

首先来看报错的makefile源码 再来看报错的信息&#xff1a; 第5行缺少分隔符&#xff0c;其实不止是第5行&#xff0c;只要是前面需要加tab留白的行都会报这个错误&#xff0c;比如说第7行第11行 编译的时候&#xff0c;前面的留白必须是按tab键生成的 但是&#xff01;&…

【JavaSE笔记】抽象类与接口

一、抽象类 1、概念 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这样的类就是抽象类。 package demo2…

DM@数理逻辑@命题公式及其赋值@真值表@公式分类

文章目录 abstract命题公式及其赋值命题常项命题变项 命题公式合式公式(命题公式)限定基本联结词的合适公式的定义合式公式中的0和1子公式 **公式的层次定义**分层加括号 命题公式的赋值和解释成真赋值成假赋值公式的书写规范括号的省略 真值表赋值方法数量构造真值表 公式分类…

Json-Jackson和FastJson

狂神&#xff1a; 测试Jackson 纯Java解决日期格式化 设置ObjectMapper FastJson&#xff1a; 知乎&#xff1a;Jackson使用指南 1、常见配置 方式一&#xff1a;yml配置 spring.jackson.date-format指定日期格式&#xff0c;比如yyyy-MM-dd HH:mm:ss&#xff0c;或者具体的…

深入理解Windows句柄

引言 我们首先需要了解在windows内核中&#xff0c;为了方便管理一些相关的数据结构&#xff0c;Windows统一把它们称之为对象。在Windows内核代码中大量代码都是用C语言编写的。而我们知道在C语言中&#xff0c;并没有纯粹的面向对象&#xff0c;也没有类这一说。因此我们可以…

ArmSoM-W3之RK3588 Debian11详解

1. 简介 RK3588从入门到精通Debian 是⼀种完全⾃由开放并⼴泛⽤于各种设备的 Linux 操作系统。Rockchip在官⽅Debian发⾏版的基础上构建和适配了相关硬件功能 2. 环境介绍 硬件环境&#xff1a; ArmSoM-W3 RK3588开发板 软件版本&#xff1a; OS&#xff1a;ArmSoM-W3 Debia…

WPF 如何让xmal的属性换行显示 格式化

WPF 如何让UI的xmal 按照下面的格式化显示 首先格式化显示在VS中的快捷键是 Ctrl &#xff2b;D 然后需要配置&#xff0c;工具 选项 -文本编辑器 -xmal -格式化-间距 更改成如下就可以了

[2023.09.12]: Yew应用开发的第一个hook--use_state

Yew的SSR模式推荐使用function_component组件&#xff0c;并且在function_component中使用hooks。其中&#xff0c;我使用到的第一个hook是use_state。use_state的设计意图与React中的useState非常相似&#xff0c;都是为了保存并修改当前的状态。然而&#xff0c;由于Yew是用R…

RK3588 点亮imx586摄像头

一.硬件原理图 mipi摄像头硬件确认点&#xff1a; 1.供电&#xff1a;5V&#xff0c;2.8V&#xff0c;1.2V&#xff0c;1.8V&#xff0c;reset脚&#xff08;硬拉3.3&#xff0c;上电的时候从低到高&#xff09;&#xff0c;pwron脚外接 3.3V。 2,时钟&#xff1a;MCLKOUT是2…

Python正则表达式(re)

正则表达式&#xff0c;又称规则表达式,&#xff08;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字符&#xff08;称为…

已知平面内三点,求其平面的法向量

三点平面法向量 设三点坐标为A(x1,y1,z1),B(x2,y2,z2),C(x3,y3,z3) 向量AB(x2-x1,y2-y1,z2-z1),AC(x3-x1,y3-y1,z3-z1) AB、AC所在平面的法向量即ABAC(a,b,c),其中&#xff1a; a(y2-y1)(z3-z1)-(z2-z1)(y3-y1) b(z2-z1)(x3-x1)-(z3-z1)(x2-x1) c(x2-x1)(y3-y1)-(x3-x1)(y2-y1)…

JavaScript-DOM实战案例

一、window定时器 1.window定时器方法 有时我们并不想立即执行一个函数&#xff0c;而是等待特定一段时间之后再执行&#xff0c;我们称之为“计划调用&#xff08;scheduling a call&#xff09;”。 目前有两种方式可以实现&#xff1a; setTimeout 允许我们将函数推迟到一…

xen-gic初始化流程

xen-gic初始化流程 调试平台使用的是gic-600&#xff0c;建议参考下面的文档来阅读代码&#xff0c;搞清楚相关寄存器的功能。 《corelink_gic600_generic_interrupt_controller_technical_reference_manual_100336_0106_00_en》 《IHI0069H_gic_architecture_specification》…

【flink进阶】-- Flink kubernetes operator 版本升级

目录 1、检查当前 flink kubernetes operator 版本 2、停止生产上正在运行的 flink job 3、升级 CRD

linux万字图文学习进程信号

1. 信号概念 信号是进程之间事件异步通知的一种方式&#xff0c;属于软中断。 1.1 linux中我们常用Ctrlc来杀死一个前台进程 1. Ctrl-C 产生的信号只能发给前台进程。一个命令后面加个&可以放到后台运行,这样Shell不必等待进程结束就可以接受新的命令,启动新的进程。2. S…

简单记录一下Splunk ES 升级

1: 背景: 现在有些app 产品对splunk ES (enterprise security) 的版本有要求,这个就要求splunk ES 随着Splunk enterprise 也一起升级,下面先列一下各个版本的兼容: Splunk products version compatibility matrix - Splunk Documentation 下面列出的8.2.11 的版本: 2:…

day38 代码回想录 斐波那契数爬楼梯使用最小花费爬楼梯

大纲 ● 理论基础 ● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯 509. 斐波那契数 题目&#xff1a;509. 斐波那契数 // 斐波那契数列 // 动规 5部曲 // 1 dp[i]代表i处的斐波那契值 // 2 递归公式&#xff1a;dp[0] 0, dp[1]1, dp[i]dp[i-1]dp[i-2] // 3…

9月16日,每日信息差

今天是2023年09月16日&#xff0c;以下是为您准备的15条信息差 第一、天猫超市首单“茅小凌”已由菜鸟送达&#xff0c;首单已由菜鸟供应链完成履约&#xff0c;18分钟送达消费者手中 第二、软银考虑对OpenAI进行投资。此外&#xff0c;软银还初步拟收购英国人工智能芯片制造…

FE_Vue学习笔记 - 数据代理

Vue中的数据代理是一种机制&#xff0c;通过它&#xff0c;Vue实例&#xff08;vm&#xff09;可以代理其数据对象&#xff08;data&#xff09;中的属性操作。这种代理的原理主要是通过Object.defineProperty()方法&#xff0c;将data对象的每个属性都添加到vm对象上&#xff…

uni-app 实现自定义按 A~Z 排序的通讯录(字母索引导航)

创建 convertPinyin.js 文件 convertPinyin.js 将下面的内容复制粘贴到其中 const pinyin (function() {let Pinyin function(ops) {this.initialize(ops);},options {checkPolyphone: false,charcase: "default"};Pinyin.fn Pinyin.prototype {init: functi…