【问题标题】:write and read a 3d vector of struct in file C++在文件 C++ 中写入和读取结构的 3d 向量
【发布时间】:2013-08-02 21:32:22
【问题描述】:

我想保存这个结构并稍后加载它:

struct Block
{
    vector<int> numbers;
    map<int , char> bits;
    map<string , string > states;
    string off;
}relationTable[7][11][13];

除了使用几个for 循环之外,还有其他方法吗? 我用这个函数来保存:

void saveData()
{
    string location = "test.bin";
    ofstream fs(location, std::ios::out | std::ios::binary | std::ios::app);
    fs.write(reinterpret_cast<const char *>(relationTable), sizeof(relationTable));
    fs.close();
}

还有这个用于加载:

void loadData()
{
    string location = "test.bin";
    Block array[64][96][2];
    ifstream file (location, ios::in|ios::binary|ios::ate);
    if (file.is_open())
    {
        file.seekg (0, ios::beg);
        file.read ((char*)&array, sizeof(array));
        file.close();
    }

    ...//some use of array
}

但它不起作用,因为它只保存指针!我该怎么办?

【问题讨论】:

  • 我不明白你想做什么......
  • 我填写了relationTable,想保存到文件或数据库中以备日后使用!
  • 你能把你的对象序列化成json格式吗?
  • 对象的写法以某种方式将其输入序列化,所以序列化算法有问题,使用boostjson即可。 json 的好处是它可以用另一种语言(如 java、python、java 脚本等)轻松阅读。
  • xml 也是一个不错的选择 :)

标签: c++ file map vector struct


【解决方案1】:

对你来说,relationTable 是什么还不是很清楚。 如果要将结构保存到文件中,更简单的方法是使用 boost::serialization 见:How do you serialize an object in C++?

你可以这样做:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/map.hpp>
include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>

namespace boost {
namespace serialization {

template<class Archive>
void serialize(Archive & ar, Block& b, const unsigned int version)
{
    ar & b.numbers;
    ar & b.bits;
    ar & b.states;
    ar & b.off;
}

void save_Block(const Block &b, const char * filename){
// make an archive
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
oa << b;
}
}}

完整的示例程序:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>

#include <fstream>

struct Block
{
    typedef std::vector<int> Numbers;
    typedef std::map<int, char> Bits;
    typedef std::map<std::string, std::string> States;

    Numbers numbers;
    Bits bits;
    States states;
    std::string off;
};

namespace boost { namespace serialization {

        template<class Archive>
            void serialize(Archive & ar, Block& b, const unsigned int version)
            {
                ar & b.numbers;
                ar & b.bits;
                ar & b.states;
                ar & b.off;
            }

} }

void save_Block(const Block &b, const char * filename){
    // make an archive
    std::ofstream ofs(filename);
    boost::archive::text_oarchive oa(ofs);
    oa << b;
}

int main()
{
    save_Block(Block { 
                   { 1, -42 },
                   { { 3, '0' }, { 17, '1' } },
                   { { "disabled", "true" }, { "locked", "false" }, { "ui", "manual" } },
                   "something called 'off'"
                },
                "test.txt");
}

文件test.txt 将包含:

22 serialization::archive 10 0 0 2 0 1 -42 0 0 2 0 0 0 3 48 17 49 0 0 3 0 0 0 8 disabled 4 true 6 locked 5 false 2 ui 6 manual 22 something called 'off'

【讨论】:

  • 你能再解释一下吗?
【解决方案2】:

我推荐

  • Boost PropertyTree(用于 Xml、Json)

    已撤销。这导致了许多开发人员数小时的哭泣和痛苦。也不要使用 PropertyTree。使用适当的 JSON 或 XML 库。

    专业提示: Boost 1.75.0+ 使用Boost JSON

  • Boost 序列化(用于二进制、xml、文本)

  • libjsoncpp(甚至this

或者.....你可以使用Boost Spirit

您可以使用 Karma 生成器来序列化 Block:

template <typename It>
    struct generator : karma::grammar<It, Block(), karma::space_type>
{
    generator() : generator::base_type(start)
    {
        using namespace karma;

        start   = numbers << bits << states << off;

        numbers = lit("numbers") << '{' << -(int_  % ',') << '}';
        bits    = lit("bits")    << '{' << -(bit   % ',') << '}';
        states  = lit("states")  << '{' << -(state % ',') << '}';
        off     = lit("off")     << string_;

        bit     = int_    << ':' << char_;
        state   = string_ << ':' << string_;

        string_ = '"' << *('\\' << char_('"') | char_) << '"';
    }
    // ...
};

这个,当像这样使用时:

static const generator<boost::spirit::ostream_iterator> gen;

std::ostringstream oss;
oss << karma::format_delimited(gen, karma::space, 
        Block { 
           { 1, -42 },
           { { 3, '0' }, { 17, '1' } },
           { { "disabled", "true" }, { "locked", "false" }, { "ui", "manual" } },
           "something called 'off'"
        }) << "\n";

将单个Block 打印到oss

numbers { 1 , -42 } bits { 3 : 0 , 17 : 1 } states { "disabled" : "true" , "locked" : "false" , "ui" : "manual" } off "something called 'off'"

然后您可以使用镜像语法将其解析回来:

Block reparsed;

std::string const input = oss.str();
auto f(begin(input)), l(end(input));
assert(qi::phrase_parse(f,l,par,qi::space,reparsed));

查看完整程序:

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>

namespace qi    = boost::spirit::qi;
namespace karma = boost::spirit::karma;

struct Block
{
    typedef std::vector<int> Numbers;
    typedef std::map<int, char> Bits;
    typedef std::map<std::string, std::string> States;

    Numbers numbers;
    Bits bits;
    States states;
    std::string off;
};

BOOST_FUSION_ADAPT_STRUCT(Block,
        (Block::Numbers, numbers)
        (Block::Bits, bits)
        (Block::States, states)
        (std::string, off))

template <typename It, typename Skipper = qi::space_type>
    struct parser : qi::grammar<It, Block(), Skipper>
{
    parser() : parser::base_type(start)
    {
        using namespace qi;

        start   = numbers >> bits >> states >> off;

        numbers = no_case ["numbers"] >> '{' >> -(int_  % ',') > '}';
        bits    = no_case ["bits"   ] >> '{' >> -(bit   % ',') > '}';
        states  = no_case ["states" ] >> '{' >> -(state % ',') > '}';
        off     = no_case ["off"    ] >> string_;

        bit     = int_    >> ':' > char_;
        state   = string_ >> ':' > string_;

        string_ = '"' >> *('\\' > char_ | ~char_('"')) > '"';

        BOOST_SPIRIT_DEBUG_NODES((start)(numbers)(bits)(states)(off)(bit)(state)(string_));
    }

  private:
    qi::rule<It, Block(), Skipper> start;
    qi::rule<It, Block::Numbers(), Skipper> numbers;
    qi::rule<It, Block::Bits(), Skipper> bits;
    qi::rule<It, Block::States(), Skipper> states;

    qi::rule<It, std::pair<int, char>(), Skipper> bit;
    qi::rule<It, std::pair<std::string, std::string>(), Skipper> state;

    qi::rule<It, std::string(), Skipper> off;
    qi::rule<It, std::string()> string_;
};

template <typename It>
    struct generator : karma::grammar<It, Block(), karma::space_type>
{
    generator() : generator::base_type(start)
    {
        using namespace karma;

        start   = numbers << bits << states << off;

        numbers = lit("numbers") << '{' << -(int_  % ',') << '}';
        bits    = lit("bits")    << '{' << -(bit   % ',') << '}';
        states  = lit("states")  << '{' << -(state % ',') << '}';
        off     = lit("off")     << string_;

        bit     = int_    << ':' << char_;
        state   = string_ << ':' << string_;

        string_ = '"' << *('\\' << char_('"') | char_) << '"';

        BOOST_SPIRIT_DEBUG_NODES((start)(numbers)(bits)(states)(off)(bit)(state)(string_));
    }

  private:
    karma::rule<It, Block(), karma::space_type> start;
    karma::rule<It, Block::Numbers(), karma::space_type> numbers;
    karma::rule<It, Block::Bits(), karma::space_type> bits;
    karma::rule<It, Block::States(), karma::space_type> states;

    karma::rule<It, std::pair<int, char>(), karma::space_type> bit;
    karma::rule<It, std::pair<std::string, std::string>(), karma::space_type> state;

    karma::rule<It, std::string(), karma::space_type> off;
    karma::rule<It, std::string()> string_;
};

int main()
{
    typedef std::string::const_iterator It;

    static const parser<It, qi::space_type> par;
    static const generator<boost::spirit::ostream_iterator> gen;

    Block reparsed;
    {
        std::ostringstream oss;
        oss << karma::format_delimited(gen, karma::space, 
                Block { 
                   { 1, -42 },
                   { { 3, '0' }, { 17, '1' } },
                   { { "disabled", "true" }, { "locked", "false" }, { "ui", "manual" } },
                   "something called 'off'"
                }) << "\n";


        std::string const input = oss.str();
        auto f(begin(input)), l(end(input));
        assert(qi::phrase_parse(f,l,par,qi::space,reparsed));

        // serialize and deserialize the whopping 3D collection of Blocks:
        std::cout << karma::format_delimited(gen, karma::space, reparsed) << "\n";
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多