C++ istream_迭代器的初始化会导致设置ifstream.fail()

C++ istream_迭代器的初始化会导致设置ifstream.fail(),c++,file-io,ifstream,istream-iterator,C++,File Io,Ifstream,Istream Iterator,我正试图将大量数据从文件导入boost::dynamic_位集中。为了实现这一点,我希望使用一个istream_迭代器,它与动态_比特集(uint32_t)的块大小相匹配 如下图所示,我使用要导入的文件的位置设置ifstream。但是,一旦我用ifstream初始化了istream_迭代器,ifstream的fail位就被设置了 关于为什么会发生这种情况,有什么建议吗 ifstream memHashes (hashFileLocation, ios::in | ios::binary); if

我正试图将大量数据从文件导入boost::dynamic_位集中。为了实现这一点,我希望使用一个istream_迭代器,它与动态_比特集(uint32_t)的块大小相匹配

如下图所示,我使用要导入的文件的位置设置ifstream。但是,一旦我用ifstream初始化了istream_迭代器,ifstream的fail位就被设置了

关于为什么会发生这种情况,有什么建议吗

ifstream memHashes (hashFileLocation, ios::in | ios::binary);
if(memHashes.is_open() == false || memHashes.good() == false) { break; }
std::istream_iterator<uint32_t> memHashesIt(memHashes);
std::istream_iterator<uint32_t> memHashesEOFIt;

我认为初始化将从流中读取uint32\t。uint32_t类型是无符号或无符号long的别名。我有一种隐隐的感觉,您的文件不包含数字,但您希望(例如,请参阅ios_base::binary openmode)流能够读取一些压缩的非文本表示。如果是这样的话,你的期望是完全错误的,但是如果你不了解你的计划,就很难说出来。不过需要注意的是:如果您一直在阅读istream_迭代器,那么您将始终同时设置eofbit和failbit。我猜您只设置了failbit,这表明存在解析错误。

std::istream\u迭代器对类型为
T
的对象使用输入
运算符>>()
。也就是说,它采用格式化输入。在构造时,它尝试读取第一个元素,这可能导致
std::istream
获得
std::ios\u base::failbit
集。

问题是您有二进制数据

istream\u迭代器
istreambuf\u迭代器
使用
操作符>
读取数据。对于uint_32_t,这意味着它将读取人类可读的文本并将其转换为整数。对于二进制数据,这将失败(大部分时间)

你对速度还有另一个误解。
一次读取4个字节的速度不可能比一次读取1个字节的速度快(这会使代码更复杂,这可能会减慢代码的速度,但读取速度不会有任何差异)。这是因为从流读取是缓冲的。当您执行读取操作时,一个巨大的块已经被读取到缓冲区中,它只是将它从一个位置复制到另一个位置

您真正想做的是定义一个类,并将数据作为单个单元复制到类中:

class ShaMine
{
    std::vector<char>  data;
    public:
        ShaMine(): data(20, '\0') {}

        friend std::istream& operator>>(std::istream& s, ShaMine& dst)
        {
            return s.read(&data[0], 20);
        }

        void poop(std::ostream& s)
        {
             s << "Hi there: Char 0 is :" << (int) data[0] << "\n";
        } 
};

int main()
{
     std::ifstream   sfile("FILE");

     for(std::istream_iterator<ShaMine> loop(sfile); loop != std::istream_iterator<ShaMine>(); ++lop)
     {
         loop->poop(std::cout);
     }
};
classshamine
{
std::矢量数据;
公众:
ShaMine():数据(20,'\0'{}
friend std::istream&operator>>(std::istream&s、ShaMine&dst)
{
返回s.read(和数据[0],20);
}
无效船尾(标准::ostream&s)
{

我以为所有的流都是字符-based@Non-StopTimeTravel将uint32_t更改为uint8_t会消除错误。令人失望的是,读取4字节的块可能比读取1字节的块更有效。我不知道为什么这是不可能的——istream_迭代器不应该一次从ifstream读取4字节吗除非数据不能作为
uint32\u t
读取,否则代码应该可以工作,文件包含什么?@JesseGood我已经添加了关于文件生成器的详细信息。生成器正在向文件中写入多个字符/uint8\t。我希望将4个uint8\t块作为单个uint32\u t块读取。@Bschlinker:按照这种逻辑,向量::迭代器应该是abl迭代器匹配容器元素类型,因此根据相同的基本推理,它们应该匹配流单元类型。我添加了显示文件生成方式的附加信息。这是真的——它是二进制流,而不是ASCII流(我猜这就是你所说的
packed
?)为什么这会阻止迭代器工作?迭代器只是在内部执行
in>>var
。失败的原因是它将提取文本,然后将其解析为数字。二进制标志不会改变这一点,读取其中的文档。您需要使用read()检索单个字节。请注意,读取是一个“未格式化的输入函数”,这就是Dietmar在上面所暗示的。这意味着每次迭代器递增时都会读取数据,通过我对代码的分析,这似乎是正确的。实际的读取操作是在迭代器递增时执行的。当然,只读意味着从底层对象读取数据,该对象可能缓冲了文件I/O。因此,在我的评测中,增加迭代器会带来很大的性能损失。@BSchlinker:是的。但是工作代码的效率要比不工作的代码高100%。先担心如何表达代码,然后再担心性能。另外,由于C++11和move运算符,复制迭代器的成本微不足道(因为它将被移动)这是另一种表明此时您不应该担心微不足道的增强的方式。
class ShaMine
{
    std::vector<char>  data;
    public:
        ShaMine(): data(20, '\0') {}

        friend std::istream& operator>>(std::istream& s, ShaMine& dst)
        {
            return s.read(&data[0], 20);
        }

        void poop(std::ostream& s)
        {
             s << "Hi there: Char 0 is :" << (int) data[0] << "\n";
        } 
};

int main()
{
     std::ifstream   sfile("FILE");

     for(std::istream_iterator<ShaMine> loop(sfile); loop != std::istream_iterator<ShaMine>(); ++lop)
     {
         loop->poop(std::cout);
     }
};