使用流C ++进行序列化

时间:2013-06-24 13:45:51

标签: c++

在此论坛上提供一些帮助后,我使用C ++实现了一些序列化/反序列化。 该文件似乎写得正确,但当我读到它时,新行被忽略,一些数据相互打印,如下所示:

enter image description here

这是我的代码。任何反馈,帮助,如何改进纠正它,非常感谢:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>      // std::ifstream
using namespace std;

struct Product
{
    double price_;
    double product_index_;
    std::string product_name_;
    std::string other_data_;

    friend std::ostream& operator<<(std::ostream& os, const Product& p)
    {
        return os << p.price_ << '\n'
                  << p.product_index_ << '\n'
                  << p.product_name_ << '\n'
                  << p.other_data_ << '\n';
    }

    friend std::istream& operator>>(std::istream& is, Product& p)
    {
        is >> p.price_ >> p.product_index_;
        is.ignore(std::numeric_limits<streamsize>::max(), '\n');

        getline(is,p.product_name_);
        getline(is,p.other_data_);

        return is;
    }
};


int _tmain(int argc, _TCHAR* argv[])
{
    Product s1,s2,s3,s4;

    s1.price_ = 100;
    s1.product_index_ = 0;
    s1.product_name_= "flex";
    s1.other_data_ = "dat001";

    s2.price_ = 200;
    s2.product_index_ = 1;
    s2.product_name_= "brr";
    s2.other_data_ = "dat002";

    s3.price_ = 300;
    s3.product_index_ = 2;
    s3.product_name_= "megatex";
    s3.other_data_ = "dat003";

    // write
    fstream file1("c:\\test.dat",ios::out|ios::binary|ios::app);
    file1_file << s1 << s2 << s3;
    file1_file.close();

    // read
    ifstream file2("c:\\test.dat");

    Product p;
    while (file2 >> p)
    {
            cout<<p.price_<<endl;
            cout<<p.product_index_<<endl;
            cout<<p.product_name_;
            cout<<p.other_data_;
    }

    if (!file2.good())
         std::cerr << "error during parsing of input file\n";
    else
        std::cerr << "error opening input file\n";

    return 0;
}

另外,为什么我最终会得到错误?

PS。与使用读取和写入的方法相比,上述方法的好处是什么,例如:write(record, sizeof(Product))seek(record_size * n, SEEK_SET)read(record, sizeof(Product))(读取第n个产品);提示:我听说过POD相关的限制和可移植性

2 个答案:

答案 0 :(得分:2)

今天,您几乎不需要实现自己的低级序列化。

尝试JSONBSONProtocol BuffersMessagePackXML

quite a lot libraries,比“自己动手”更好......

您打算编写二进制序列化,但是插入EOL('\ n')字符。这不是将二进制流划分为令牌的好选择。

答案 1 :(得分:1)

错误消息的原因很明确:您输入 binary_file2直到输入失败(通常是因为存在 没有更多的数据,因为你已到达文件的末尾),那么你说 如果任何输入失败,则输出“输入文件的错误解析”。

至于丢失新行,请阅读product_name_other_data_ std::getline使用cout来提取。{1}} 最终换行符,但将其插入到字符串中 读。在您输出到endl的循环中,您 在每个字段后需要write(record, sizeof(Product))

关于你的问题:这样做的主要优点 你的方式,而不是使用std::setw等,它是有效的。一般来说, 你不能写出你在内存中所拥有的二进制图像,以及 期望能够正确地重读它们。如果你想成为 能够寻找(可能有用),你必须定义 输出文件中的固定长度表示。 (这可以 通过强制每个输出字段具有固定长度来完成 {{1}}。)