基于Ofstream的类覆盖文件

问题描述 投票:0回答:1

我为我的一个C++项目创建了一个“File”类,它基于ofstream。这是简化的代码:

文件.h

#include <fstream>
#include <mutex>
#include <filesystem>
#include <vector>

class File
{
private:
  std::ofstream writer;
  static std::mutex file_mtx;

  std::filesystem::path path;

public:
  File();
  File(const std::filesystem::path &_path);

  void write(const std::vector<std::string> &lines);
};

文件.cpp

File::File(const std::filesystem::path &_path) : path(_path)
{
    // Create file
    std::lock_guard<std::mutex> lock(file_mtx);
    writer.open(path, std::ios::app);
    writer.close();
}

void File::write(const std::vector<std::string> &lines)
{
    std::lock_guard<std::mutex> lock(file_mtx);
    writer.open(path, std::ios::app);

    if (!writer.is_open())
        return;

    for (const auto &line : lines)
        writer << line
               << "\n";
    
    writer.close();
}

std::mutex File::file_mtx;

我仅在需要提高效率时才使用 ofstream 打开文件,并且使用互斥锁来防止两个不同的对象同时写入同一文件。写入功能也在附加模式下打开(

std::ios::app
)。

这是我的“测试”代码:

#include "file.h"

int main(int argc, char *argv[])
{
  File test("./test.txt");
  test.write({
    "Hello",
    "World"
  });

  File test2("./test.txt");
  test2.write({
    "Part",
    "2"
  });

  return 0;
}

我对同一个文件有两个不同的变量的原因是因为在我的实际代码中,必须在两个不同的作用域中访问该文件,因此必须定义两个变量。

这是文件的输出:

Part
2

这是预期的输出:

Hello
World
Part,
2

尽管互斥体在函数开始时被锁定,并且尽管文件以追加模式打开,但文件仍然会被覆盖。我想知道为什么会发生这种情况,以及为什么互斥体首先不能阻止文件被覆盖。

这是我的最小可重现示例:

#include <fstream>
#include <mutex>
#include <filesystem>
#include <vector>

class File
{
private:
  std::ofstream writer;

  std::filesystem::path path;

public:
  File(const std::filesystem::path &_path) : path(_path)
  {
    // Create file
    writer.open(path, std::ios::app);
    writer.close();
  }

  void write(const std::vector<std::string> &lines)
  {
    if (!writer.is_open())
      return;

    for (const auto &line : lines)
      writer << line
             << "\n";

    writer.close();
  }
};

int main(int argc, char *argv[])
{
  File test("./test.txt");
  test.write({"Hello",
              "World"});

  File test2("./test.txt");
  test2.write({"Part",
               "2"});

  return 0;
}
c++ file mutex ofstream
1个回答
0
投票

您的问题与互斥体无关。在您最初发布的代码中,该文件在构造函数中重新创建:

File::File(const std::filesystem::path& _path) : path(_path)
{
  // Create file
  std::lock_guard<std::mutex> lock(file_mtx);
  writer.open(path);
  writer.close();
}

然后将上面的代码替换为:

File(const std::filesystem::path& _path) : path(_path)
{
  // Create file
  writer.open(path, std::ios::app);
  writer.close();
}

此代码不会重新创建文件,但不会产生预期的结果,因为文件是以追加模式打开的。因此,每次运行程序时,都会附加文本:

Hello
World
Part
2
Hello
World
Part
2...

您可能想要的是

Reset
方法:

File(const std::filesystem::path& _path) : path(_path)
{
  // no code here
}

void Reset()
{
  // the code you originally placed in constructor 
}

int main(int argc, char* argv[])
{
  File("./test.txt").Reset();

  // ...
}
© www.soinside.com 2019 - 2024. All rights reserved.