首页 > 解决方案 > 从全局对象的构造函数调用 std::ofstream 时不创建文件

问题描述

首先 - 编写的代码在 Linux 中工作,但在 Windows 上构建和运行时,不会创建日志文件。

我创建了一个简单的日志库,它应该创建一个可执行文件的本地文件。

记录器.h

#ifndef LOGGER_H
#define LOGGER_H

namespace Logger
{
    enum class Level
    {
        DEBUG,
        INFO,
        WARNING,
        ERROR
    };

    std::string GetTime();

    class Log
    {
    private:
        std::string filename;
        std::stringstream inStr;
        std::ofstream logFile;
        std::recursive_mutex inStrMutex;
        std::mutex fileMutex;

        void ClearStrStream();
        std::string LevelToString(Level lvl);

    public:
        Log(std::string file);
        ~Log();

        template<typename T>
        void Write(Level lvl, const T& arg)
        {
            std::lock_guard<std::recursive_mutex> inStrLock(inStrMutex);
            std::lock_guard<std::mutex> fileLock(fileMutex);

            inStr << std::noskipws << arg << '\n';
            logFile << std::noskipws << "[" << GetTime() << "]"
                    << "[" << LevelToString(lvl) << "] "
                    << inStr.str();

            ClearStrStream();

            return;
        }

        template<typename T, typename... Args>
        void Write(Level lvl, const T& firstArg, Args... args)
        {
            std::lock_guard<std::recursive_mutex> lock(inStrMutex);
            inStr << std::noskipws << firstArg;
            Write(lvl, args...);
            return;
        }

    };
}

#endif

Logger.cpp 中定义的构造函数

Logger::Log::Log(std::string file) : filename{ file }
{
    std::cout << "Ctor called\n";
    auto now = Logger::GetTime();
    auto fullName =  now + "_" + filename;
    logFile = std::ofstream(fullName);

    inStr = std::stringstream("", std::ios_base::ate | std::ios_base::out | std::ios_base::in);
}

这被构建到一个静态库中,然后链接到 LoggerUnitTest.cpp

#include <chrono>
#include <fstream>
#include <iostream>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
#include <functional>

#include "Logger.h"
#include "LoggerConfig.h"
#include "date.h"

Logger::Log GLogObject("LoggerTest.log");

void WriteToLogger()
{
    GLogObject.Write(Logger::Level::WARNING,
                     "The quick brown ",
                     "fox jumps ",
                     "over the ",
                     "lazy ",
                     "dog.");

    GLogObject.Write(Logger::Level::ERROR,
                     "Because nighttime ",
                     "is the best time ",
                     "to fight crime.");

    return;
}

void TestMultipleTypes()
{
    GLogObject.Write(Logger::Level::DEBUG,
                     "String ",
                     123,
                     " and integer.");

    return;
}

int main()
{
    std::cout << "Testing Logger Version: " << LOGGER_VERSION_MAJOR << "."
              << LOGGER_VERSION_MINOR << std::endl;

    std::thread t1(TestMultipleTypes);
    std::thread t2(WriteToLogger);
    WriteToLogger();
    std::thread t3(WriteToLogger);
    WriteToLogger();
    std::thread t4(WriteToLogger);
    std::thread t5(WriteToLogger);

    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();

    return 0;
}

当 LoggerUnitTest 在 Linux 中构建并运行时,一切都按预期工作。创建一个日志文件,并将所有内容按预期写入日志文件。

在 Windows 中构建和运行 LoggerUnitTest 时,LoggerUnitTest.exe 会运行,但不会创建日志文件。Windows 有什么不同导致没有文件被写入?

我还尝试显式添加std::flushLogger 的 Write 函数,这似乎没有什么区别。

标签: c++

解决方案


问题在于 GetTime() 返回日期/时间格式字符串的方式。甲酸盐为 YYYY/mm/DD_HH:MM:SS。根据Microsoft Docs,冒号:和正斜杠/是文件名中的禁止字符。调整日期/时间格式后,一切正常!


推荐阅读