c++ boost::iostreams中的接收设备仅在关闭时写入磁盘

0ve6wy6x  于 11个月前  发布在  iOS
关注(0)|答案(1)|浏览(128)

我正在尝试编写一个“Sink Device”,用于boost::iostreams库。我想实现一个写磁盘上文件的流,但是这样的写只有在流退出作用域时才能完成。这个想法是在实际写操作完成之前,文件不会被触及。(原因是,在实际代码中,写操作可能发生在流打开的时间之后,在这段时间内,我希望能够检查文件;如果我只是在写模式下打开一个fstream,它会立即被擦除)。
tutorial之后,我写了一个“Sink device”,它等待在磁盘上写入,直到析构函数被调用。
下面是一个工作代码:

#include <exception>
#include <fstream>
#include <iosfwd>                          // streamsize
#include <sstream>
#include <string>
#include <boost/iostreams/categories.hpp>  // sink_tag
#include <boost/iostreams/stream.hpp>

class delayed_file_sink {
  std::string m_filename;
  std::ostringstream m_buf;

public:
  typedef char      char_type;
  typedef boost::iostreams::sink_tag  category;

  std::streamsize write(const char* s, std::streamsize n)
  {
    auto cur = m_buf.str().size();
    m_buf.write(s, n);
    auto now = m_buf.str().size();
    return (now - cur);
  }

  delayed_file_sink(const std::string& filename) : m_filename{filename}
     { std::cout << "Constructor is called" << std::endl; }
  // does not compile without copy constructor
  delayed_file_sink(const delayed_file_sink& other) : m_filename{other.m_filename}, m_buf{other.m_buf.str()}
     { std::cout << "Copy Constructor is called" << std::endl; }
  ~delayed_file_sink() noexcept(false) {
    try {
      std::cout << "Destructor is called" << std::endl;
      std::fstream file(m_filename, std::ios_base::out);
      if (!file.good())
         throw(std::runtime_error(std::string("Error opening file ") + m_filename));
      file << m_buf.str();
    }
    catch (const std::exception& e) {
      // Silent catch exception if nothing has been written and stack is unwinding
      if ((std::uncaught_exceptions() == 0) || (m_buf.str().size() > 0))
    throw (e);
    }
  }
};

using delayed_ofstream = boost::iostreams::stream<delayed_file_sink>;

int main()
{
  std::cout << "about to create object delayed_ofstream" << std::endl;
  delayed_ofstream info{"info.dat"};
  std::cout << "about to exit" << std::endl;

  return 0;
}

字符串
与我的预期相反,在main()中创建delayed_ofstream对象后,文件立即被擦除。原因可以通过上面程序的输出来理解(我插入了一些“打印”来监视发生了什么):

about to create object delayed_ofstream
Constructor is called
Copy Constructor is called
Copy Constructor is called
Copy Constructor is called
Destructor is called
Destructor is called
Destructor is called
about to exit
Destructor is called


这个输出表明,在内部,库复制了3次对象。然后一些副本超出了作用域,析构函数被调用,结果是擦除文件。
理想情况下,让这样一个设备“不可复制”是有意义的,但是如果没有复制构造函数,代码就无法编译。
有没有办法告诉boost::iostreams库设备是不可复制的?或者我如何修复代码?

62lalag4

62lalag41#

Boost iostream设备需要是可复制的(正如您所发现的),该库早于可移动类型,因此可以大量复制设备。
为了弥补这一点,设备通常使用shared_ptr来保持它们的状态。例如,参见basic_file,它有一个shared_ptr<impl> pimpl_成员。
你应该做类似的事情,有一个共享的impl类,并在销毁这个impl类时写文件,而不是在销毁每个设备时写文件。

相关问题