I have a binary file. There are 2288*2288 longitude float values stored in top half section, and the same number of latitude float values occupied the bottom half. I used the following code to load them into a float vector. It can run like a charm, but gave me incorrect results. With regard to my binary file, the float vector should be filled with a total of 2288*2288*2=10469888 elements, but only 159005, all their values are the same 200.0000. Would you please explain what's wrong with my code?
Thank you in advance!
bool LoadData(const char* pszDataFile)
{
typedef char_traits<float> traits_type;
typedef std::codecvt<float, char, mbstate_t> cvt;
std::basic_ifstream<float, traits_type> input( pszDataFile, std::ios::binary );
std::locale loc(std::locale(), new cvt());
input.imbue(loc);
std::vector<float> fvBuffer;
// Copies all data into buffer
std::copy(std::istreambuf_iterator<float>(input),
std::istreambuf_iterator<float>( ),
std::back_inserter(fvBuffer));
long nSzie = fvBuffer.size(); // Wrong vector size (159005)
return true;
}
To make std::basic_ifstream works, you have to define your trait_type so that it provides everything expected by input stream, and I'm not sure that it will be possible. That will be far more than just a codecvt<float, char, mbstate_t>
(which you seem to think is already present while the standard demand only the wchar_t, char and char, char specializations).
If you want a binary input iterator, you'll have to write one yourself to work with basic_ifstream, something like this (run and give the expected result, but not debugged further):
#include <fstream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
template <typename T>
class BinaryInputIterator
: public std::iterator<std::input_iterator_tag, T, std::ptrdiff_t,
const T*, const T&>
{
public:
BinaryInputIterator();
BinaryInputIterator(std::istream&);
// Compiler generated version OK:
// BinaryInputIterator(BinaryInputIterator const& other);
// BinaryInputIterator& operator=(BinaryInputIterator const& other);
~BinaryInputIterator();
T const& operator*() const;
T const* operator->() const;
BinaryInputIterator& operator++();
BinaryInputIterator operator++(int);
private:
std::istream* myStream;
T myValue;
friend bool operator==
(BinaryInputIterator const& l, BinaryInputIterator const& r)
{
return ((l.myStream == NULL && (r.myStream == NULL || !*r.myStream))
|| (r.myStream == NULL && (l.myStream == NULL || !*l.myStream)));
}
friend bool operator!=
(BinaryInputIterator const& l, BinaryInputIterator const& r)
{
return !(l == r);
}
};
template <typename T>
BinaryInputIterator<T>::BinaryInputIterator()
: myStream(0)
{}
template <typename T>
BinaryInputIterator<T>::BinaryInputIterator(std::istream& is)
: myStream(&is)
{
myStream->read(reinterpret_cast<char*>(&myValue), sizeof myValue);
}
template <typename T>
BinaryInputIterator<T>::~BinaryInputIterator()
{}
template <typename T>
T const& BinaryInputIterator<T>::operator*() const
{
return myValue;
}
template <typename T>
T const* BinaryInputIterator<T>::operator->() const
{
return &myValue;
}
template <typename T>
BinaryInputIterator<T>& BinaryInputIterator<T>::operator++()
{
myStream->read(reinterpret_cast<char*>(&myValue), sizeof myValue);
return *this;
}
template <typename T>
BinaryInputIterator<T> BinaryInputIterator<T>::operator++(int)
{
BinaryInputIterator result(this);
++*this;
return result;
}
int main()
{
{
std::ofstream os("foo.dta");
std::vector<float> vect1;
vect1.push_back(4.2);
vect1.push_back(3.14);
os.write(reinterpret_cast<char*>(&vect1[0]), sizeof(float)*vect1.size());
}
{
std::ifstream is("foo.dta");
std::vector<float> vect2;
std::copy(BinaryInputIterator<float>(is),
BinaryInputIterator<float>(),
std::back_inserter(vect2));
std::copy(vect2.begin(), vect2.end(), std::ostream_iterator<float>(std::cout, "\n"));
}
}