最简轮转日志的核心是每次写入前检查文件名日期是否匹配当天:不匹配则关闭旧文件、用新日期路径重新打开;需用strftime("%Y-%m-%d")统一格式,避免手拼或格式符错误,并注意多线程下ofstream非线程安全。

用 std::ofstream + 时间判断实现最简轮转
不依赖第三方库时,核心就一条:每次写日志前检查当前文件名是否匹配今天日期。不匹配就关掉旧文件、打开新文件。
常见错误是只在程序启动时打开一次文件,后续永远不检查日期——结果日志全堆进昨天的文件里。
- 每次写入前调用
std::localtime获取当前日期,格式化为"2024-05-21"这种字符串 - 维护一个
std::string current_date_str记录当前写入的日期,和实时计算的做比较 - 不一致时,先
file.close(),再用新日期拼路径(如"log_2024-05-21.txt"),然后file.open(...) - 注意
std::ofstream的is_open()检查,避免重复 close 或 open 失败后继续写
strftime 格式字符串别写错,否则日期总对不上
轮转失效最常见的原因是时间解析出错——比如把 %Y 写成 %y(前者是 4 位年,后者是 2 位),或者漏了 %02d 导致 2024-5-1 和 2024-05-01 被当成两个不同文件。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 推荐固定用
strftime(buf, sizeof(buf), "%Y-%m-%d", &tm),严格保证格式统一 - 不要手拼字符串:
std::to_string(tm.tm_year + 1900) + "-" + std::to_string(tm.tm_mon + 1)容易缺前导零 - 如果用 C++20 的
<chrono>,记得用std::format("{:%Y-%m-%d}", sys_time)(需编译器支持),否则退回到strftime
多线程写日志时,std::ofstream 不是线程安全的
多个线程同时调用 file 可能导致内容错乱、换行丢失,甚至 <code>ofstream 内部状态损坏。这不是轮转逻辑的问题,但会让轮转看起来“偶尔失灵”。
立即学习“C++免费学习笔记(深入)”;
- 必须加锁:用
std::mutex log_mutex包住整个“检查日期 → 打开/切换 → 写入”流程 - 不能只锁写入部分,否则两个线程可能同时判断“该切文件”,然后都去
close()同一个流 - 如果性能敏感,考虑无锁队列 + 单独日志线程,但轮转逻辑仍得在该线程内集中处理
Windows 下路径分隔符和文件权限容易踩坑
Linux 下 "./log/log_" + date + ".txt" 没问题,Windows 上如果目录 log/ 不存在,ofstream::open 会静默失败——你还在往一个没打开的流里写,什么都不会输出,也看不到错误。
- 写入前先用
std::filesystem::create_directories("log/")(C++17)确保路径存在 - Windows 默认对中文路径支持弱,日志文件名含中文时可能打不开;坚持用 ASCII 日期格式最稳妥
- 某些环境(如服务进程)工作目录不可写,要写绝对路径,比如
"C:/myapp/logs/log_" + date + ".txt"


















