为什么basic_ifstream显示错误的结果



我有一个二进制文件。上半部分存储了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"));
 }
}

相关内容

  • 没有找到相关文章

最新更新