我有一个二进制文件。上半部分存储了2288*22288个经度浮动值,下半部分则存储了相同数量的纬度浮动值。我使用以下代码将它们加载到一个浮点向量中。它可以像符咒一样运行,但给了我不正确的结果。关于我的二进制文件,浮点向量应该填充总共2288*22288*2=10469888个元素,但只有159005个,它们的所有值都是相同的200.0000。你能解释一下我的代码出了什么问题吗?
提前谢谢!
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;
}
如果在文件打开后输入()文件流,则输入()将自动失败。
您必须执行imbue(),然后打开文件:
std::basic_ifstream<float, traits_type> input;
std::locale loc(std::locale(), new cvt());
input.imbue(loc);
// Open after the imbue()
input.open( pszDataFile, std::ios::binary );
你的第二个问题是你混淆了术语二进制文件:
此代码使用操作员>>读取文本数据流(即文本文件)
std::copy(std::istreambuf_iterator<float>(input),
std::istreambuf_iterator<float>( ),
std::back_inserter(fvBuffer));
打开文件时使用std::ios::binary
只会影响"行末序列"(EOLS)的生成方式,与文件的性质无关。尽管由于指定了它,"\n"字符不会转换为EOLS,这在生成二进制文件时很有用。
因此,简单的答案是,你最好从文件中读取文本流。
向量比预期的要短的原因是流读取遇到错误,因此停止了对读取请求的响应。
此外,我无法编译您的代码
所以你在做一些非标准的事情。
要使std::basic_ifstream工作,您必须定义trait_type,以便它提供输入流所需的一切,我不确定这是否可能。这将远远不止是一个codecvt<float, char, mbstate_t>
(您似乎认为它已经存在,而标准只需要wchar_t,char和char,char专业化)。
如果你想要一个二进制输入迭代器,你必须自己写一个来处理basic_ifstream,类似这样的东西(运行并给出预期的结果,但没有进一步调试):
#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"));
}
}