广告位联系
返回顶部
分享到

Qt实现日志文件的滚动写入

C语言 来源:互联网 作者:佚名 发布时间:2024-11-19 08:27:47 人浏览
摘要

Qt 日志文件的滚动写入 flyfish 日志文件的滚动写入功能。在日志文件达到10MB时创建新的日志文件,并且在总日志文件大小达到10GB时开始覆盖最早的日志文件 以监控一个文件夹的写日志为例 日

Qt 日志文件的滚动写入

flyfish

日志文件的滚动写入功能。在日志文件达到10MB时创建新的日志文件,并且在总日志文件大小达到10GB时开始覆盖最早的日志文件

以监控一个文件夹的写日志为例

日志文件创建与管理

初始化日志文件:在FileMonitor类的构造函数中,会创建第一个日志文件。日志文件的命名格式为 “file_monitor_序号.log”,初始序号为 0。

滚动写入机制

单个日志文件大小限制:当向当前日志文件写入内容使得其大小达到 10MB(通过logFileSizeLimit变量设定,值为10 * 1024 * 1024字节)时,会关闭当前日志文件,增加日志文件索引,然后创建新的日志文件用于后续的日志记录。

总日志文件大小限制

同时,会监控所有日志文件的总体大小,当总大小达到 10GB(通过totalLogSizeLimit变量设定,值为10 * 1024 * 1024 * 1024字节)时,会删除最早创建的日志文件(通过计算最早日志文件的文件名并判断其是否存在,若存在则删除),以确保总日志文件大小不会无限制增长。

日志内容记录

对于文件创建、删除、修改等事件,会将事件发生的当前日期时间(格式为 “yyyy-MM-dd hh:mm:ss”)、事件类型(如 “File created”、“File deleted”、“File modified”)以及相关文件的路径信息,按照特定格式写入到当前正在使用的日志文件中。并且每次写入后会立即刷新缓冲区,确保日志内容及时写入文件。同时,会实时更新当前日志文件的大小信息,以便判断是否达到单个日志文件大小限制。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

#include <QCoreApplication>

#include <QFileSystemWatcher>

#include <QFile>

#include <QTextStream>

#include <QDateTime>

#include <QDir>

#include <QFileInfo>

#include <QSet>

#include <iostream>

 

// FileMonitor类继承自QObject,用于监控指定文件夹的文件变化并记录相关日志

class FileMonitor : public QObject {

    Q_OBJECT

 

public:

    // 构造函数,用于初始化文件监控器相关参数

    explicit FileMonitor(const QString &path, QObject *parent = nullptr)

        : QObject(parent),

          // 创建文件系统监控器对象,并将其作为当前对象的子对象

          watcher(new QFileSystemWatcher(this)),

          rootPath(path),

          // 设置单个日志文件的大小限制为10MB,这里将10MB转换为字节数

          logFileSizeLimit(static_cast<quint64>(10) * 1024 * 1024),

          // 设置总日志文件大小限制为10GB,同样转换为字节数

          totalLogSizeLimit(static_cast<quint64>(10) * 1024 * 1024 * 1024),

          currentLogFileIndex(0),

          currentLogFileSize(0) {

 

        // 将指定的监控路径添加到文件系统监控器中

        watcher->addPath(rootPath);

 

        // 获取监控路径下初始的文件列表

        QDir dir(rootPath);

        initialFiles = dir.entryList(QDir::Files);

 

        // 连接文件系统监控器的目录变化信号到对应的槽函数

        connect(watcher, &QFileSystemWatcher::directoryChanged, this, &FileMonitor::onDirectoryChanged);

        // 连接文件系统监控器的文件变化信号到对应的槽函数

        connect(watcher, &QFileSystemWatcher::fileChanged, this, &FileMonitor::onFileChanged);

 

        // 初始化日志文件,创建第一个日志文件

        createNewLogFile();

    }

 

private slots:

    // 当监控的目录发生变化时调用的槽函数

    void onDirectoryChanged(const QString &path) {

        std::cout << "Directory changed: " << qPrintable(path) << std::endl;

 

        // 获取当前监控目录下的文件列表

        QDir dir(rootPath);

        QStringList currentFiles = dir.entryList(QDir::Files);

 

        // 找出新增的文件,通过集合运算实现

        QSet<QString> newFiles = QSet<QString>(currentFiles.begin(), currentFiles.end()).subtract(QSet<QString>(initialFiles.begin(), initialFiles.end()));

        // 遍历新增的文件,记录文件创建事件到日志

        for (const QString &file : newFiles) {

            logEvent("File created", dir.absoluteFilePath(file));

        }

 

        // 找出被删除的文件,同样通过集合运算

        QSet<QString> deletedFiles = QSet<QString>(initialFiles.begin(), initialFiles.end()).subtract(QSet<QString>(currentFiles.begin(), currentFiles.end()));

        // 遍历被删除的文件,记录文件删除事件到日志

        for (const QString &file : deletedFiles) {

            logEvent("File deleted", dir.absoluteFilePath(file));

        }

 

        // 更新初始文件列表,使其为当前的文件列表,以便下次检测文件变化

        initialFiles = currentFiles;

    }

 

    // 当监控的文件发生变化时调用的槽函数

    void onFileChanged(const QString &path) {

        std::cout << "File changed: " << qPrintable(path) << std::endl;

        // 记录文件修改事件到日志

        logEvent("File modified", path);

    }

 

private:

    // 创建新的日志文件的函数

    void createNewLogFile() {

        // 构造新的日志文件名,格式为:file_monitor_序号.log

        QString logFileName = "file_monitor_" + QString::number(currentLogFileIndex) + ".log";

        currentLogFile.setFileName(logFileName);

 

        // 如果日志文件已经存在,获取其大小并更新当前日志文件大小变量

        if (currentLogFile.exists()) {

            currentLogFileSize = currentLogFile.size();

        } else {

            currentLogFileSize = 0;

        }

 

        // 打开或创建日志文件,如果失败则输出错误信息

        if (!currentLogFile.open(QIODevice::Append | QIODevice::Text)) {

            std::cerr << "Failed to open/create log file: " << qPrintable(logFileName) << std::endl;

        }

    }

 

    // 记录日志事件的函数

    void logEvent(const QString &event, const QString &path) {

        // 创建文本流对象,用于向当前日志文件写入内容

        QTextStream out(&currentLogFile);

        // 写入当前日期时间、事件类型和文件路径信息到日志文件

        out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")

            << " - " << event << ": " << path << "\n";

        currentLogFile.flush();

 

        // 计算刚写入的日志字符串的大小,先读取文本流中的内容

        QString logString = out.readAll();

        // 如果读取为空,说明可能是因为刚刚写入还未缓存,重新构造日志字符串

        if (logString.isEmpty()) {

            logString = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")

                        + " - " + event + ": " + path + "\n";

        }

 

        // 更新当前日志文件的大小,将日志字符串转换为UTF-8编码后计算其字节数并累加到当前日志文件大小变量

        currentLogFileSize += logString.toUtf8().size();

 

        // 检查当前日志文件大小是否达到单个日志文件大小限制

        if (currentLogFileSize >= logFileSizeLimit) {

            // 关闭当前日志文件

            currentLogFile.close();

 

            // 增加日志文件索引,用于创建下一个新的日志文件

            ++currentLogFileIndex;

 

            // 检查是否超过了总日志文件大小限制,如果超过则删除最早的日志文件

            if (currentLogFileIndex * logFileSizeLimit > totalLogSizeLimit) {

                QString oldestLogFileName = "file_monitor_" + QString::number(currentLogFileIndex - totalLogSizeLimit / logFileSizeLimit) + ".doc";

                if (QFile::exists(oldestLogFileName)) {

                    QFile::remove(oldestLogFileName);

                }

            }

 

            // 创建新的日志文件

            createNewLogFile();

        }

    }

 

    // 文件系统监控器对象,用于监控指定路径下的文件和目录变化

    QFileSystemWatcher *watcher;

    // 监控的根路径

    QString rootPath;

    // 初始的文件列表,用于对比检测文件的新增和删除情况

    QStringList initialFiles;

 

    // 以下是新增的日志管理相关成员变量

 

    // 当前正在使用的日志文件对象

    QFile currentLogFile;

    // 单个日志文件的大小限制,单位为字节

    quint64 logFileSizeLimit;

    // 总日志文件大小限制,单位为字节

    quint64 totalLogSizeLimit;

    // 当前日志文件的索引,用于区分不同的日志文件

    quint64 currentLogFileIndex;

    // 当前日志文件的大小,单位为字节,用于实时监控文件大小是否达到限制

    quint64 currentLogFileSize;

};

 

int main(int argc, char *argv[]) {

    QCoreApplication a(argc, argv);

 

    // 获取命令行参数,如果有参数则将其作为监控路径,否则默认监控根目录

    QString watchPath = (argc > 1)? QString::fromLocal8Bit(argv[1]) : "/";

 

    // 创建文件监控对象,传入监控路径

    FileMonitor monitor(watchPath);

 

    // 运行应用程序的事件循环,开始监控文件和目录变化并记录日志

    return a.exec();

}

 

#include "main.moc"


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • C++中std::thread{}和std::thread()用法
    std::thread{}和std::thread()用法 在C++中,std::thread是用于处理线程的类。 关于std::thread{}和std::thread()的区别,主要涉及到C++11引入的统一初始化(
  • Qt实现日志文件的滚动写入
    Qt 日志文件的滚动写入 flyfish 日志文件的滚动写入功能。在日志文件达到10MB时创建新的日志文件,并且在总日志文件大小达到10GB时开始覆盖
  • Java打印星号图案和数字图案的代码
    使用循环和控制语句打印图案 在 Java 中,使用循环和控制语句是打印图案的最佳方法。循环可以帮助你重复执行一段代码,直到满足某个条
  • 解读构造函数的调用规则、深拷贝与浅拷贝

    解读构造函数的调用规则、深拷贝与浅拷贝
    1.调用规则 默认情况下,C++至少会给一个类添加三个函数: 默认构造函数(无参,函数体为空) 默认析构函数(无参,函数体为空) 默认
  • Qt音视频功能实现方法

    Qt音视频功能实现方法
    Qt 音视频 在 Qt 中,音频主要是通过QSound类来实现。但是需要注意的是QSound类只支持播放wav格式的音频文件。也就是说如果想要添加音频效果
  • C++的dynamic代码介绍
    在C++编程中,dynamic_cast是处理多态类型转换的关键工具,允许在复杂继承结构中安全地将基类指针或引用转换为派生类指针或引用。通过利
  • C++中使用不同平台的时间函数及对比介绍
    在 C++ 编程中,时间函数的选择对于性能测量、任务调度和时间戳记录至关重要。不同的操作系统提供了不同的时间函数,同时在同一个平台
  • C++中VTK9.3.0刻度标签重叠的问题记录

    C++中VTK9.3.0刻度标签重叠的问题记录
    本文采用VTK9.3.0版本,其他版本如VKT8.0亦有同样的问题 VTK显示文本时,Z轴刻度标签出现了重叠,如下图: 寻找好久,没有找到设置标签间距
  • C++拷贝构造函数和赋值运算符重载介绍

    C++拷贝构造函数和赋值运算符重载介绍
    一,拷贝构造函数 1. 什么是拷贝构造函数 拷贝构造函数是特殊的构造函数。是用一个已经存在的对象,赋值拷贝给另一个新创建的已经存在
  • C++中生成随机数的方法介绍

    C++中生成随机数的方法介绍
    背景 C++ 11 在头文件 #include 中定义了随机数库,也可以使用 C 中生成随机数的方法。 C 生成随机数 概述 C 语言中使用 rand() 函数产生 0 ~ RA
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计