【问题标题】:Good practice to write binary stream to either a file or stdout将二进制流写入文件或标准输出的好习惯
【发布时间】:2019-03-16 18:01:38
【问题描述】:
#include <fstream> 
#include <vector>
#include <iostream>

int main()
{
    bool bWriteConsole = true;
    std::streambuf *buf;
    std::ofstream outfile;

    if (bWriteConsole)
        buf = std::cout.rdbuf();
    else
    {
        outfile.open("./hello.bin", std::ofstream::binary | std::ofstream::out);
        buf = outfile.rdbuf();
    }

    std::ostream outstream(buf);
    std::vector<char> m_tableBuffer;
    double dValue = 1.2345;
    const void* dBytes = &dValue;
    std::copy(static_cast<const char *>(dBytes), static_cast<const char *>(dBytes) + sizeof(double), std::back_inserter(m_tableBuffer));

    outstream.write((char*)m_tableBuffer.data(), m_tableBuffer.size());

    if (!bWriteConsole)
        outfile.close();
    else
        std::cout << std::flush;

    return 0;
}

我需要向我现有的应用程序添加一个函数,以便它可以将二进制流输出到标准输出而不是文件。原型如上图所示。

问题> 这个实现有什么问题吗?有没有不考虑 RAII 的优雅解决方案?

谢谢

== 基于来自 luk32 的 cmets 更新

void function2()
{
    bool bWriteConsole = true;
    std::ofstream outfile;

    if (!bWriteConsole)
        outfile.open("./hello.bin", std::ofstream::binary | std::ofstream::out);

    std::vector<char> m_tableBuffer;
    double dValue = 1.2345;
    const void* dBytes = &dValue;
    std::copy(static_cast<const char *>(dBytes), static_cast<const char *>(dBytes) + sizeof(double), std::back_inserter(m_tableBuffer));

    if (!bWriteConsole)
    {
        outfile.write((char*)m_tableBuffer.data(), m_tableBuffer.size());
        outfile.close();
    }
    else
    {
        std::cout.write((char*)m_tableBuffer.data(), m_tableBuffer.size());
        std::cout.flush();
    }
}

【问题讨论】:

  • 为什么不让函数简单地接受std::ostream&amp; 并传入std::ofstreamstd::cout
  • 简单地使用std::ostream::write(reinterpret_cast&lt;char*&gt;(T&amp;), sizeof T)有什么问题?您没有缓冲区也没有副本,也不需要通过创建另一个具有相同rdbufostream 来制作cout 的半副本。 cout 已经是 ostream。您是否有理由将内存内容复制到中间缓冲区?
  • @luk32,对于直接输出到标准输出,我没有理由缓冲结果。但是,对于直接输出到文件,我必须先将结果缓冲到内存中,然后最后将所有内容刷新到文件中。
  • @luk32,我正在阅读这篇文章stackoverflow.com/questions/366955/…
  • 为什么? ofstreamcout 本质上没有区别。您链接的问题有这一行“虽然由于很多原因这无效,但我想实现[...]”。我倾向于同意这种情绪。可能是 XY 问题。 ofstreamcout(因为它是 ostream)都被缓冲了。他们都提供flush

标签: c++11 centos


【解决方案1】:

我的版本会更类似于这个:

#include <iostream>
#include <fstream>

void function2(bool bWriteConsole)
{
    std::ofstream outfile;

    if (!bWriteConsole)
        outfile.open("./hello.bin", std::ofstream::binary | std::ofstream::out);

    double dValue = 1.2345;

    // writing out
    std::ostream& out = bWriteConsole ? std::cout : outfile;
    out.write(reinterpret_cast<char*>(&dValue), sizeof dValue);
    out.flush();
}

编写代码是 2 行,如果您真的想刷新,则需要 3 行。 outfile.close() 也会刷新,因此无条件刷新与您的方法相比没有任何害处。当outfile 超出范围时文件将被关闭,因此除非您真的想在进一步处理之前手动关闭文件,否则不必写入文件。在这里它是多余的(RAII 善良在这里发挥作用)。

Aaand 也许重构写作:

template<typename T>
void dump(T val, std::ostream& out ) {
    out.write(reinterpret_cast<char*>(&val), sizeof val);
    out.flush();
}

void function2(bool bWriteConsole)
{
    std::ofstream outfile;

    if (!bWriteConsole)
        outfile.open("./hello.bin", std::ofstream::binary | std::ofstream::out);

    double dValue = 1.2345;
    dump(dValue, bWriteConsole ? std::cout : outfile);
    // writing out
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-09
    • 2019-09-04
    • 2010-12-01
    • 2014-09-07
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多