流为什么要继续阅读并且不会达到eof?

时间:2014-09-25 10:02:50

标签: c++ stream eof

我实现了一个非常简单的序列化库,用于保存/恢复 user_info 对象,其中包含一个int和一个std :: string,这里是我的代码:

#include <iostream>
#include <sstream>
using namespace std;

struct user_info {
    int id;
    string name;
};

// for any POD type like int, read sizeof(int) from the stream
template <class stream_t, class T>
void de_serialize(stream_t& stream, T& x) {
    stream.read((char*)&x, sizeof(T));
}

// for std::string, read length(int) first, then read string content when length>0
template <class stream_t>
void de_serialize(stream_t& stream, std::string& str) {
    int len;
    de_serialize(stream, len);
    str.resize(len);
    char x;
    for(int i=0; i<len; i++) {
        de_serialize(stream, x);
        str[i] = x;
    }
}

// read from stream, fill id and name
template <typename stream_t>
void de_serialize(stream_t& ss, user_info& ui) {
    de_serialize(ss, ui.id);
    de_serialize(ss, ui.name);
}


int main() {
    // read from file, but here I use a 8-bytes-content represents the file content
    stringstream ifs;
    // two int, \x1\x1\x1\x1 for id, \x0\x0\x0\x0 for name
    ifs.write("\x1\x1\x1\x1\x0\x0\x0\x0", 8);
    while(!ifs.eof()) {
        user_info ui;
        de_serialize(ifs, ui);
        // when first time goes here, the stream should've read 8 bytes and reaches eof, 
        // then break the while loop, but it doesn't
        // so the second time it calls de_serialize, the program crashes
    }
}

代码说明了反序列化的部分。 while循环应该运行一次,流到eof,但为什么它不会停止循环?第二个循环导致崩溃。

请参阅评论,谢谢。

1 个答案:

答案 0 :(得分:1)

如果streem出现错误情况,则永远不会设置eof()标志。循环eof()通常是错误的。我在这里要做的是从de_serialize()函数更改返回类型以返回流,然后围绕de_serialize()函数重写循环

像这样:

#include <iostream>
#include <sstream>
using namespace std;

struct user_info {
    int id;
    string name;
};

// for any POD type like int, read sizeof(int) from the stream
template <class stream_t, class T>
stream_t& de_serialize(stream_t& stream, T& x) {
    stream.read((char*)&x, sizeof(T));
    return stream; // return the stream
}

// for std::string, read length(int) first, then read string content when length>0
template <class stream_t>
stream_t& de_serialize(stream_t& stream, std::string& str) {
    int len;
    de_serialize(stream, len);
    str.resize(len);
    char x;
    for(int i=0; i<len; i++) {
        de_serialize(stream, x);
        str[i] = x;
    }
    return stream; // return the stream
}

// read from stream, fill id and name
template <typename stream_t>
stream_t& de_serialize(stream_t& ss, user_info& ui) {
    de_serialize(ss, ui.id);
    de_serialize(ss, ui.name);
    return ss; // return the stream
}


int main() {
    // read from file, but here I use a 8-bytes-content represents the file content
    stringstream ifs;
    // two int, \x1\x1\x1\x1 for id, \x0\x0\x0\x0 for name
    ifs.write("\x1\x1\x1\x1\x0\x0\x0\x0", 8);

    user_info ui;
    while(de_serialize(ifs, ui)) { // loop on de_serialize()

        // Now you know ui was correctly read from the stream

        // when first time goes here, the stream should've read 8 bytes and reaches eof,
        // then break the while loop, but it doesn't
        // so the second time it calls de_serialize, the program crashes
    }
}