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

news2024/11/18 9:24:09

文章目录

  • 专栏导读
  • 获取系统时间
    • 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/1001629.html

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

相关文章

智慧公厕助力数字强市建设,打造善感知新型信息化公共厕所

随着城市建设的不断发展&#xff0c;智慧公厕作为一个重要的基础设施&#xff0c;正逐渐受到人们的重视。智慧公厕不仅为人们提供舒适的使用环境&#xff0c;更是通过数字化技术的应用&#xff0c;为城市发展注入新的动力。本文将以智慧公厕源头厂家广州中期科技有限公司&#…

我是如何用 redis 分布式锁来解决线上历史业务问题的

近期发现&#xff0c;开发功能的时候发现了一个 mq 消费顺序错乱&#xff08;历史遗留问题&#xff09;&#xff0c;导致业务异常的问题&#xff0c;看看我是如何解决的 问题抛出 首先&#xff0c;简单介绍一下情况&#xff1a; 线上 k8s 有多个 pod 会去消费 mq 中的消息&a…

编写更嵌入式软件代码的10个技巧

代码维护是应用程序开发的重要方面&#xff0c;而为了缩短上市时间&#xff0c;通常会忽略代码维护。对于某些应用程序&#xff0c;这可能不会造成重大问题&#xff0c;因为这些应用程序的寿命很短&#xff0c;或者已部署该应用程序&#xff0c;并且再也不会碰它。 但是&#x…

UIScrollView setContentOffset: animated:

项目中遇到感觉一切都设置对了&#xff0c;但是看到的效果和预想的不一样。 后来查询了一番&#xff0c;才知道问题所在&#xff0c;现在记录一下&#xff0c;担心过后又忘了。 最初的问题是这样的&#xff0c;这个热度只有在评论里有&#xff0c;点击赞的时候&#xff0c;热度…

视频号的视频怎么下载,有什么下载工具推荐

视频下载助手去水印小工具是一款方便实用的工具&#xff0c;可以帮助用户在下载视频的时候可以一键去除视频中的水印。 该工具支持多种视频平台的去水印功能&#xff0c;如抖音、快手、小红书、视频号、公众号文字视频、西瓜视频、哔哩哔哩、微博视频、多多视频等。 经过亲自测…

为什么女程序员那么稀缺?女程序员吃不吃香?

程序员脱单一直是个难题&#xff0c;这里的一个客观原因就是程序员群体的男女比例严重失衡&#xff08;比如我司达到了2:8&#xff09;&#xff0c;身边的工作环境缺少异性&#xff0c;大老爷们天天混在一起&#xff0c;脱单自然也就更加困难了。 女程序员那么稀缺&#xff0c…

《Python深度学习-Keras》精华笔记3:解决深度学习多分类问题

公众号&#xff1a;机器学习杂货店作者&#xff1a;Peter编辑&#xff1a;Peter 持续更新《Python深度学习》一书的精华内容&#xff0c;仅作为学习笔记分享。 本文是第三篇&#xff1a;介绍如何使用Keras解决Python深度学习中的多分类问题。 多分类问题和二分类问题的区别注意…

180页的Python完全版电子书

大家好&#xff0c;我是涛哥。 Python学习有很多方式&#xff0c;可以从基础一步步看语法&#xff0c; 可以从案例一步步学习&#xff0c;本篇内容就是通过案例进行讲解&#xff0c;方便大家一步一步进行学习实战。 整个内容经过几个月总结《Python之路2.0.pdf》&#xff0c…

基于 Python 的音乐流派分类

音乐就像一面镜子&#xff0c;它可以告诉人们很多关于你是谁&#xff0c;你关心什么&#xff0c;不管你喜欢与否。我们喜欢说“you are what you stream” - Spotify Spotify 拥有 260 亿美元的净资产&#xff0c;是如今很受欢迎的音乐流媒体平台。它目前在其数据库中拥有数百…

Java拓展--空间复杂度和时间复杂度

空间复杂度和时间复杂度 文章目录 空间复杂度和时间复杂度空间复杂度时间复杂度**评价排序算法****时间频度****什么是时间频度****忽略常数项****忽略低次项****忽略系数** **时间复杂度****什么是时间复杂度****计算时间复杂度的方法****常见的时间复杂度** **常见的时间复杂…

正中优配:证券融资融券是什么意思?

证券融资融券&#xff08;简称“融资融券”&#xff09;是一种股票出资办法&#xff0c;是指出资者经过融券生意和融资生意来进行股票出资。它在出资商场上具有重要的作用&#xff0c;因为经过这种办法&#xff0c;出资者能够使用假贷资金进行股票生意&#xff0c;能够进步出资…

腾讯云4核8G服务器选CVM还是轻量比较好?价格对比

腾讯云4核8G云服务器可以选择轻量应用服务器或CVM云服务器标准型S5实例&#xff0c;轻量4核8G12M服务器446元一年&#xff0c;CVM S5云服务器935元一年&#xff0c;相对于云服务器CVM&#xff0c;轻量应用服务器性价比更高&#xff0c;轻量服务器CPU和CVM有区别吗&#xff1f;性…

23062C++QTday4

仿照string类&#xff0c;完成myString 类 代码&#xff1a; #include <iostream> #include <cstring> using namespace std; class myString {private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度public://无参构造my…

华为云云耀云服务器L实例评测 | 由于自己原因导致MySQL数据库被攻击 【更新中。。。】

目录 引出起因&#xff08;si因&#xff09;解决报错诶嘿&#xff0c;连上了 不出意外&#xff0c;就出意外了打开数据库what&#xff1f;&#xff1f;&#xff1f; 找华为云求助教训&#xff1a;备份教训&#xff1a;密码 解决1.改密码2.新建一个MySQL&#xff0c;密码设置复杂…

Android T 窗口层级其三 —— 层级结构树添加窗口

文章目录 序节点添加Task以DefaultTaskDisplayArea为父节点以Task为父节点 ActivityRecordWindowTokenWindowState以WindowToken为父节点以ActivityRecord为父节点 小结调用场景添加差异 流程分析添加log堆栈打印流程LauncherStatusBar 序 尚未添加窗口的层级结构树&#xff0…

前端该了解的网络知识

网络 前端开发需要了解的网络知识 URL URL(uniform resource locator,统一资源定位符)用于定位网络服务. URL是一个固定格式的字符串 它表达了: 从网络中哪台计算机(domain)中的哪个服务(port),获取服务器上资源的路径(path),以及要用什么样的协议通信(schema). 注意: 当…

探索Netty的FuturePromise

Netty—Future&Promise 一、JDK原生 Future二、Netty包下的 Future三、Promise1、使用Promise同步获取结果2、使用Promise异步获取结果.3、使用Promise同步获取异常 - sync & get4、使用Promise同步获取异常 - await5、使用Promise异步获取异常 在异步处理时&#xff0…

颜色代码对照表

颜色代码对照表 各颜色代码: 1 白色 #FFFFFF 2 红色 #FF0000 3 绿色 #00FF00 4 蓝色 #0000FF 5 牡丹红 #FF00FF 6 青色 #00FFFF 7 黄色 #FFFF00 8 黑色 #000000 9 海蓝 #70DB93 …

出行类APP商业化路径解决方案

当下市场主流的商业化路径和方法相比于之前区别不大&#xff0c;开发者们都是在现有商业化体系下&#xff0c;制定更加详细、优质的策略&#xff0c;以期获得更高利益。 出行类App用户结构分析 年龄层次&#xff1a;出行类App用户的年龄分布比较广泛&#xff0c;主要集中在20…

商品防伪查询溯源小程序开发源码

企业商家在销售商品的过程中被人仿冒产品以次充好损害公司名声和影响产品销量是很多企业的痛点。我们基于次帮助企业开发了一款商品防伪溯源查询小程序&#xff0c;解决企业痛点&#xff0c;酿造更好的经商坏境。 核心功能&#xff1a; 我们采用一物一码的逻辑&#xff0c;可…