使用std::ostream_iterator将内容写入二进制文件

3

考虑以下代码:

std::vector<long> d(3);
d[0] = 0;
d[1] = 1;
d[2] = 2;

std::ofstream f("d:/ofstream.txt", std::ios_base::binary);
std::ostream_iterator<long> out(f);

std::copy(std::begin(d), std::end(d), out);

由于文件大小仅为3字节,因此它被写为char而不是long。在这种情况下我能使用std::ostream_iterator吗?

我无法理解它在这里的行为。

1个回答

4
std::stream_iterator使用“正常”的operator<<语义,它是一种格式化输出(而不是二进制)。引用自cppreferencestd::ostream_iterator是单向输出迭代器,将类型为T的连续对象写入构造它的std::basic_ostream对象中,使用operator<<。可选的分隔符字符串在每个写操作后写入输出流。当分配给迭代器(无论是否解引用)时执行写操作。增加std::ostream_iterator是一个空操作。您可以实现一个自定义迭代器,将未格式化的输出写入流;它将需要遵循与std::stream_iterator相同的约束条件,特别是:operator=将对象写入相关的输出序列。在这种情况下,应将对象作为未格式化数据(原始二进制内容)写入流中。您的确切实现可能会有所不同,但在这里,我们使用简单的二进制转储进行演示。
#include <iostream>
#include <algorithm>
#include <utility>
#include <iterator>

using namespace std;

template <class T, class CharT = char, class Traits = std::char_traits<CharT>>
class ostreambin_iterator :
    public std::iterator<std::output_iterator_tag, void, void, void, void> {
public:
    typedef std::basic_ostream<CharT, Traits> ostream_type;
    typedef Traits traits_type;
    typedef CharT  char_type;

    ostreambin_iterator(ostream_type& stream) : stream_(stream) { }

    ostreambin_iterator& operator=(T const& value) 
    {
        // basic implementation for demonstration
        stream_.write(reinterpret_cast<const char*>(&value), sizeof(T));
        return *this;
    }

    ostreambin_iterator& operator*()     { return *this; }
    ostreambin_iterator& operator++()    { return *this; }
    ostreambin_iterator& operator++(int) { return *this; }

protected:
    ostream_type& stream_;
};

int main() {
    std::vector<long> d(3);
    d[0] = 0x303030; // test some width past a single byte
    d[1] = 0x31;
    d[2] = 0x32;

    ostreambin_iterator<long> out(cout);

    cout << "begin" << endl;
    copy(std::begin(d), std::end(d), out);
    cout << endl;
    cout << "end" << endl;
}

演示现场

本次演示中我使用了cout(所以在你的控制台上可能看不到NULL字节)。


针对后置和前置自增运算的实现,这个指针需要进行递增吗? - Steephen
@Steephen。不,对于这个ostreambin_iterator模型的ostream_iterator来说,前置和后置递增运算符是无操作的。这是有道理的,因为流本身管理底层缓冲区中的位置、插入等操作。 - Niall
感谢澄清。 - Steephen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接