C++ C++;将一个对象写入一个文件,然后再将其读入?

C++ C++;将一个对象写入一个文件,然后再将其读入?,c++,serialization,object,C++,Serialization,Object,可能重复: 我最近一直在玩弄C++,现在只与OfSt流有过几次体验。所说的大多数经验都是对变量进行简单的文件输出,并使用ifstream将它们读回。我没有做过任何关于对象的事情 让我们假设我有一个经常被写入的对象(比如一个游戏,对象就是角色),每当角色被击中时,hp就会被重新写入,每当他们击败敌人时,他们就会获得经验。。。。我的基本想法是写一个简单的基于文本的地牢爬行游戏。但是我该如何制作某种自动保存文件??我是否只是将对象的每个属性单独写入一个文件中,然后再从那里转到更大更好的位置?如果我

可能重复:

我最近一直在玩弄C++,现在只与OfSt流有过几次体验。所说的大多数经验都是对变量进行简单的文件输出,并使用ifstream将它们读回。我没有做过任何关于对象的事情

让我们假设我有一个经常被写入的对象(比如一个游戏,对象就是角色),每当角色被击中时,hp就会被重新写入,每当他们击败敌人时,他们就会获得经验。。。。我的基本想法是写一个简单的基于文本的地牢爬行游戏。但是我该如何制作某种自动保存文件??我是否只是将对象的每个属性单独写入一个文件中,然后再从那里转到更大更好的位置?如果我必须现在就做,我会这样做,但我忍不住觉得还有比这更简单的方法

有人愿意帮我将整个对象的内容(及其各自的属性)输出到一个文件中吗?

搜索web等“序列化”。需要注意的是:浮点、endianess和可变长度字段(字符串)


祝你好运

只需将对象的内容复制到内存中,即可将其写入文件

但接下来你就遇到了棘手的问题!您不能复制任何指向内存的指针,因为当您将它们加载回内存时,它们并不拥有该内存。这意味着复制像std::string这样的东西可能在内部包含它们自己的内存分配也是很棘手的

然后,即使使用标准类型,如果您计划在具有不同位数或不同字节顺序的不同机器上读取它们,也会出现问题


这个过程被称为-有一些标准技术可以使它变得更简单。

看看下面的代码:

//! Struct for a 2d marker
struct Marker2d{
    double  x;                    //!< x coordinate of marker in calibration phantom
    double  y;                    //!< y coordinate of marker in calibration phantom
    int     id;                   //!< some unique id (used for sequence id as well as for assigned 3d id)
    int     code;                 //!< type of marker (small = 0, large = 1)
    float   size;                 //!< real size of marker in 2D image (in pixel)
    double  distanceToNearest;    //!< distance to nearest other marker

    /**
    *  Overloaded stream insertion operator. Abbreviation for the output of 2d marker.
    \param  output_out A reference to an std::ostream instance indicating the output stream
    \param  marker_in A constant Marker2d reference indicating the 2d marker that we want to output
    \return a std::ostream reference containing the new output data
    */
    friend std::ostream & operator<<(std::ostream & output_out, const Marker2d & marker_in)
    {
        return output_out<< std::fixed << std::setprecision(15) <<marker_in.x<<"\t"<<marker_in.y<<"\t"<<marker_in.id<<"\t"
        <<marker_in.code<<"\t"<<marker_in.size<<"\t"<<marker_in.distanceToNearest;
    }

    /**
    *  Overloaded stream extraction operator.
    \param  s_in A reference to an std::istream instance indicating the input stream
    \param  marker_out A Marker2d reference indicating the 2d marker that will have its data members populated
    \return a std::istream reference indicating the input stream
    */
    friend std::istream& operator>>(std::istream& s_in, Marker2d & marker_out)
    {
        s_in >> marker_out.x >> marker_out.y >> marker_out.id >> marker_out.code >> marker_out.size >> marker_out.distanceToNearest;
        return s_in;
    }
};
/!二维标记的结构
结构标记2D{
校准体模中标记的双x;/!friend std::ostream&operator在你简单的问题后面隐藏着一个复杂的主题。请看一下boost::serialization(例如)。花在学习boost上的任何时间都是非常值得的。

boost中有一个很好的库,名为。如果你想提高性能,这可能不是一个正确的选择,但是查看源代码和用法可能会给你一些想法。序列化/反序列化可能很棘手,特别是当你有很多嵌套组件时。JSON是这是一种很好的序列化一般对象的格式。

这里有一个黑客把戏,很可能会让这里的程序员扯掉头发对着我尖叫(这只适用于静态对象,而不适用于使用动态内存分配的对象):

其结果是:

数字是:1000
静态数组为:数据输入
300 200 100
数字是:1000
静态数组为:数据输入
300 200 100

打开文件将显示写入的数据:
è数据输入w,Èd


上面的技巧可以很容易地转换成基于字节的格式。当然,这是一种很粗糙的方法,但是类(或对象)是应该提供他们自己的对象到字符数组的转换过程。

这是一个好的开始,但一旦你接触到更复杂的对象,比如那些包含数组、字符串或指针的对象,就会产生欺骗。另外,我很确定友元函数的定义必须在类之外,你的代码是不正确的。@MooingDuck代码是完美的,是一个非常大的项目的一部分。所以你的否决票毫无意义。而且OP想要一些简单的东西,所以我给出了一个简单的答案。我被纠正了。我一直被告知插入/提取操作符必须在类外,不能在类内。codepad说我错了。我会撤回仅此一项,-1,但我不能,除非有编辑。@MooingDuck已编辑。仅为您:DYou甚至不允许
memcpy
std::string
;任何不能在同一次程序运行中合法逐位复制的类型都不能写入文件/在另一次程序运行中读回。但即使是写入/读回n
int
将文件格式与控制
short
int
long
double
…注意:sizeof(“输入数据”)>sizeof(静态数组)长度的体系结构和特定编译器选项相关联.和静态…命名在这里是误导性的。我认为正确的命名惯例应该是POD…如果我还有一些头发,也许我现在可以把它们剪掉!
std::vector<Marker2d> myMarkers;
std::ifstream f( fileName_in.c_str() );
if(!f)
   throw std::exception(std::string("AX.Algorithms.ComputeAssignmentsTest::getMarkersFromFile - Could not open file : " + fileName_in + " for reading!").c_str());

//cool one liner to read objects from file...
std::copy(std::istream_iterator<AX::Calibration::Marker2d>(f), std::istream_iterator<AX::Calibration::Marker2d>(), std::back_inserter(myMarkers));
class TestA
{
    private:
        long Numerics;
        char StaticArray[10];
        int Data[3];

    public:
        TestA(){Numerics = 10; strcpy(StaticArray,"Input data"); Data[0] = 100; Data[1] = 200; Data[2] = 300;}
        void Test(){Numerics = 1000; strcpy(StaticArray,"Data input"); Data[0] = 300; Data[1] = 200; Data[2] = 100;}

        void Print()
        {
            printf("Numerics is: %ld\nStaticArray is: %s\n%d %d %d\n",Numerics,StaticArray,Data[0],Data[1],Data[2]);
        }
};

int main()
{
    TestA Test;
    FILE *File = fopen("File.txt","wb");
    Test.Test();
    Test.Print();
    fwrite((char *)&Test,sizeof(Test),1,File); //Treats the object as if it is a char array
    fclose(File);

    TestA Test2;
    File = fopen("File.txt","rb");
    fread((char *)&Test2,sizeof(Test2),1,File); //Treats the object as if it is a char array
    Test2.Print();
    fclose(File);
    return 0;
}