简体   繁体   中英

Getting desired binary data ranges from std::istreambuf_iterator and std::ifstream

#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>

int main()
{
    std::ifstream file("data.bin", std::ios::binary );

    if( file.fail() )
    {
        std::cout << "File does not exist or could not open file";

        return 0;
    }

    std::vector<short> buffer;

    std::copy( 
            std::istreambuf_iterator<char>( file ),
            std::istreambuf_iterator<char>(),
            std::back_inserter( buffer )
            );

   return 0;
}

This only gives me ranges of char values (-128, 128).

I thought using istreambuf_iterator<short> would give me what I want but it throws an "invalid conversion" error.

What can I do to read binary values that are in the short range?

The class std::istreambuf_iterator<cT> iterates over the characters extracted from a std::basic_istream<cT, std::char_traits<cT>> or, actually, its std::basic_streambuf<cT, std::char_traits<cT>> . That is, given a specific stream type, there is no choice for the std::istreambuf_iterator<cT> . Also note that the IOStream layer is not intended to operate on binary files, despite the std::ios_base::binary operation which is passed to the stream buffers.

If you want to extract short s (or any other type than the stream's character type) you'd need to create a suitable iterator yourself which takes the chosen binary format the file was written in into account. This iterator can be built in terms of std::istreambuf_iterator<char> or directly access the std::streambuf .

Here's my recommended Spirit approach:

#include <fstream>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

int main()
{
    std::ifstream file("data.bin", std::ios::binary);
    if(!file)
        std::cout << "File does not exist or could not open file";
    boost::spirit::istream_iterator f(file), l;

    std::vector<int16_t> buffer;
    bool ok = qi::parse(f, l, *qi::word, buffer);
}

Of course, there is qi::dword , qi::qword , big-endian/little-endian variatations etc.:


You can look at wchar_t

#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
    std::wifstream file("data.bin", std::ios::binary );
    if( file.fail() )
    {
        std::cout << "File does not exist or could not open file";
        return 0;
    }
    std::vector<wchar_t> buffer;
    std::copy( 
            std::istreambuf_iterator<wchar_t>( file ),
            std::istreambuf_iterator<wchar_t>(),
            std::back_inserter( buffer )
            );
}

I'm not too sure whether the actual size of wchar_t is implementation defined.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM