Download binary using fstream

I am trying to download a binary using fstream as follows:

 #include <iostream> #include <fstream> #include <iterator> #include <vector> using namespace std; int main() { basic_fstream<uint32_t> file( "somefile.dat", ios::in|ios::binary ); vector<uint32_t> buffer; buffer.assign( istream_iterator<uint32_t, uint32_t>( file ), istream_iterator<uint32_t, uint32_t>() ); cout << buffer.size() << endl; return 0; } 

But that will not work. On Ubuntu, it crashed with the exception std::bad_cast . In MSVC ++ 2008, it just prints 0.

I know that I could use file.read to load the file, but I want to use iterator and operator>> to load parts of the file. Is it possible? Why does the above code not work?

+3
source share
4 answers
  • istream_iterator wants basic_istream as an argument.
  • Cannot overload operator>> inside basic_istream class.
  • Defining a global operator>> will compile temporary conflicts with a member of the operator>> class.
  • You can specialize basic_istream for type uint32_t . But for specialization you have to rewrite all fductionons of the basic_istream class. Instead, you can define a dummy class x and specialize basic_istream for it, as in the following code:
 using namespace std; struct x {}; namespace std { template<class traits> class basic_istream<x, traits> : public basic_ifstream<uint32_t> { public: explicit basic_istream<x, traits>(const wchar_t* _Filename, ios_base::openmode _Mode, int _Prot = (int)ios_base::_Openprot) : basic_ifstream<uint32_t>( _Filename, _Mode, _Prot ) {} basic_istream<x, traits>& operator>>(uint32_t& data) { read(&data, 1); return *this; } }; } // namespace std int main() { basic_istream<x> file( "somefile.dat", ios::in|ios::binary ); vector<uint32_t> buffer; buffer.assign( istream_iterator<uint32_t, x>( file ), istream_iterator<uint32_t, x>() ); cout << buffer.size() << endl; return 0; } 
+3
source

The main question is probably what you mean by "binary". ios::binary only ensures that the istream object istream not replace newlines in newlines with '\ n'. Nothing more. Is that enough for you?

An istream_iterator is basically just a fancy way to call operator>> . If you have real binary data in your stream, this will fail. Do you have real binary data in your file? Or integers stored as strings?

If you need to read real binary integers, then you need either istream.read() or use the stream buffer object directly.

0
source

You can reload the operator β†’ to correctly read integers. Of course, all he does is read () 4 bytes. But what all the other operators β†’ end up doing.

Here is an example (no error checking, assuming endianess matches the current time compiler used, etc.)

 std::istream& operator>>(std::istream& in, uint32_t& data) { in.read(&data, sizeof(data)); return in; } 

Taylor for your own coloring of integers (you may have to read one byte at a time and assign them an offset, look at the file in a hex editor if you don’t know the byte order), add error checking, and you should be able to use the existing one the code.

EDIT: ah and yes, make sure that this shadow is provided to the stl statement that reads an integer - you may need to extract your own class from the stream you are using and use it instead of std :: istream & in, so the compiler knows who must first check.

0
source

Another way to do the same as Alexey Malistov:

 #include <fstream> #include <iterator> #include <vector> #include <iostream> struct rint // this class will allow us to read binary { // ctors & assignment op allows implicit construction from uint rint () {} rint (unsigned int v) : val(v) {} rint (rint const& r) : val(r.val) {} rint& operator= (rint const& r) { this->val = r.val; return *this; } rint& operator= (unsigned int r) { this->val = r; return *this; } unsigned int val; // implicit conversion to uint from rint operator unsigned int& () { return this->val; } operator unsigned int const& () const { return this->val; } }; // reads a uints worth of chars into an rint std::istream& operator>> (std::istream& is, rint& li) { is.read(reinterpret_cast<char*>(&li.val), 4); return is; } // writes a uints worth of chars out of an rint std::ostream& operator<< (std::ostream& os, rint const& li) { os.write(reinterpret_cast<const char*>(&li.val), 4); return os; } int main (int argc, char *argv[]) { std::vector<int> V; // make sure the file is opened binary & the istream-iterator is // instantiated with rint; then use the usual copy semantics std::ifstream file(argv[1], std::ios::binary | std::ios::in); std::istream_iterator<rint> iter(file), end; std::copy(iter, end, std::back_inserter(V)); for (int i = 0; i < V.size(); ++i) std::cout << std::hex << "0x" << V[i] << std::endl; // this will reverse the binary file at the uint level (on x86 with // g++ this is 32-bits at a time) std::ofstream of(argv[2], std::ios::binary | std::ios::out); std::ostream_iterator<rint> oter(of); std::copy(V.rbegin(), V.rend(), oter); return 0; } 
0
source

All Articles