You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++如何检测文件已被当前进程打开 满足日志追加开发需求

C++ 多位置复用日志文件输出实现问题

需求背景

我需要实现一个日志工具,可根据用户配置从代码的不同位置输出到相同或不同文件:若文件未打开则新建日志文件,若已打开则直接向文件追加内容。

使用如下原生写法会抢占文件流并重建文件:

std::ofstream f1("log");
f1 << "1 from f1\n";
std::ofstream f2("log");
f2 << "1 from f2\n";
f1 << "2 from f1\n";

该写法运行后日志仅保留1 from f2内容。若使用append模式打开,虽能复用文件但第二次打开会抢占f1的流,最终日志仅存在前两行写入内容,f1的后续写入会丢失。

现有方案缺陷

  • 提前预判所有要用到的日志文件并在程序启动时全部打开:方案可行,但会创建大量实际未使用的文件
  • 每次写日志都临时以追加模式打开、写完就关闭:可实现需求,但会产生大量系统调用和刷盘操作,性能过低

我打算自己维护一个已打开文件的静态表,期望用std::filesystem::canonical处理路径适配全场景,但我理解这类已打开文件映射表本就应该存在于进程的某处。我了解Fortran可以用inquire语句检测文件是否已打开,也查阅了相关问题,但没有找到C/C++下的实现方案。


内容更新

我基于静态已打开文件表实现了一个简易日志工具,代码如下:

//hpp
class Logger {
  static std::mutex _mutex;
  static std::unordered_map<std::string, std::ofstream> _openFiles;
  std::ostream& _appender;
  std::ostream& _createAppender(const std::filesystem::path& logPath);
public:
  Logger(const std::filesystem::path& logPath):
    _appender(_createAppender(logPath)) {
  }
  template<class... Args>
  void log(const Args&... args) const {
    std::scoped_lock<std::mutex> lock(_mutex);
    (_appender << ... << args);
  }
};
//cpp
#include "Logger.hpp"

std::mutex Logger::_mutex;
std::unordered_map<std::string, std::ofstream> Logger::_openFiles;

std::ostream& Logger::_createAppender(const std::filesystem::path& logPath) {
  if (logPath.empty()) return std::cout;
  const auto truePath{std::filesystem::weakly_canonical(logPath).string()};
  std::scoped_lock<std::mutex> lock(_mutex);
  const auto entry{_openFiles.find(truePath)};
  if (entry != _openFiles.end()) return entry->second;
  _openFiles.emplace(truePath, logPath);
  std::ostream& stream{_openFiles[truePath]};
  stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
  return stream;
}

该实现或许可以帮到有相同需求的人。但我还是想知道是否可以直接从系统获取提到的句柄/描述符映射表,如果有人能说明如何在程序内实现该功能,我会采纳对应答案。


内容的提问来源于stack exchange,提问作者Askold Ilvento

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 20:45:01