Qt中持续写入文本文件时如何保留最新数据并限制文件大小
Qt日志文件截断:保留最新内容而非旧数据
当你调用QFile::resize(100*1024*1024)时,只会保留文件开头的100MB内容,这显然不符合你保留最新数据的需求。正确的做法是提取文件末尾的目标大小内容,替换原文件,具体实现方案如下:
核心思路
当文件体积超过600MB时,计算出需要保留的最新100MB数据的起始位置,将这部分内容复制到临时文件,再用临时文件替换原文件,确保只保留最新的日志内容。
具体实现代码
void truncateLogToLatest(const QString& logPath, qint64 maxFileSize = 600LL * 1024 * 1024, qint64 reserveSize = 100LL * 1024 * 1024) { QFile logFile(logPath); // 文件不存在或未达到阈值,直接返回 if (!logFile.exists() || logFile.size() <= maxFileSize) { return; } // 计算要保留的最新内容的起始位置 qint64 startPos = logFile.size() - reserveSize; startPos = qMax(startPos, 0LL); // 避免出现负数位置 // 打开原日志文件读取内容 if (!logFile.open(QIODevice::ReadOnly)) { qWarning() << "无法打开日志文件读取:" << logFile.errorString(); return; } // 创建临时文件存储最新内容 QString tempPath = logPath + ".tmp"; QFile tempFile(tempPath); if (!tempFile.open(QIODevice::WriteOnly)) { qWarning() << "无法创建临时文件:" << tempFile.errorString(); logFile.close(); return; } // 跳转到目标起始位置 if (!logFile.seek(startPos)) { qWarning() << "日志文件定位失败:" << logFile.errorString(); logFile.close(); tempFile.close(); tempFile.remove(); return; } // 分块复制内容,避免一次性加载大文件占用过多内存 const qint64 blockSize = 4096; char buffer[blockSize]; qint64 bytesRead; while ((bytesRead = logFile.read(buffer, blockSize)) > 0) { tempFile.write(buffer, bytesRead); } // 关闭所有文件句柄 logFile.close(); tempFile.close(); // 替换原文件:先删除旧文件,再重命名临时文件 logFile.remove(); if (!tempFile.rename(logPath)) { qWarning() << "临时文件替换原日志失败:" << tempFile.errorString(); tempFile.remove(); } }
注意事项
- 分块复制:采用固定大小缓冲区循环读写,避免一次性加载100MB数据到内存,降低程序内存压力
- 原子性操作:先写入临时文件,确认写入成功后再替换原文件,防止原文件损坏
- 权限检查:确保程序对日志文件路径拥有读写权限,否则替换文件时会失败
- 检查时机:可以保持你当前每分钟检查一次的逻辑,也可以在每次写入日志后触发检查(适合写入频率较低的场景)
内容的提问来源于stack exchange,提问作者Rajendra Aware
相关产品推荐
相关产品推荐

