如何将模板化对象数组保存到文件中?

时间:2017-05-29 22:53:32

标签: c++ arrays io

我有一个名为

的班级
Array<T>

您可以创建任何类型的数组。

template <typename T>
    class Array
    {
    private:
        T *m_array;
        int m_size;
        ...

例如,

Array <int> myArray(32) 

是int类型的数组,大小为32.这可以存储基本类型或复杂对象。例如,

Array<Monster> monsters(32)

可以容纳一组怪物对象。无论使用什么类型,我都想从磁盘保存并加载数组。

其中一个对象,比如Actor,有一个std :: string类型的成员变量(名称)。因此,它存储为

Array<Actor> actors(32)

我今天意识到C的I / O函数对std :: string一无所知,所以从文件加载std :: string导致关闭时崩溃。我想将我的保存/加载功能升级到C ++的等价物。我的假设是这将解决我的问题,即保存和加载具有类型为std :: string的成员变量的对象。

我原来的保存/加载功能: (因为模板的工作方式,它们位于标题中,我应该提到它们是更正式的Array成员,或Array :: save()和Array :: load()。)

            bool save(const string filename)
        { 
            FILE *fOut = NULL; 
            int written = 0;

            // Validate the array
            if (!isValidArray())
                return false;

            // Open the file
            fOut = fopen(filename.c_str(), "wb");
            if (fOut == NULL)
                return false; 

            // Write the array's size to file.
            fwrite(&m_size, sizeof(int), 1, fOut);

            // Write the array to file.
            written = fwrite(m_array, sizeof(T), m_size, fOut);
            fclose(fOut);

            // Validate if the array was written correctly
            if (written != m_size)
                return false; 

            return true;
        }

负载:

bool load(const string filename)
        {
            FILE *fIn = NULL;
            int read = 0;
            int size = 0;  

            // Open the file
            fopen_s(&fIn, filename.c_str(), "rb");
            if (fIn == NULL)
                return false;

            // Read the array's size from file.
            fread(&size, sizeof(int), 1, fIn);

            // Rleease the old array 
            release();

            // Initialize the new array
            if (!init(size))
                return false;

            // Read the array from file.
            read = fread(m_array, sizeof(T), size, fIn);
            fclose(fIn);

            // Validate if the array was written correctly.
            // If not, clean up the array object.
            if (read != size)
            {
                if (m_array != NULL)
                {
                    delete[] m_array;
                    m_array = NULL;
                    m_size = 0;
                }

                return false;
            } 

            return true;
        }

总的来说,我想将这些转换为C ++的文件处理。

这是我使用save()的C ++尝试:

        bool save(const string filename)
        {  
            ofstream fOut; 

            // Validate the array
            if (!isValidArray())
                return false;

            // Open the file
            fOut.open(filename.c_str(), std::ios::binary | std::ios::out);
            if (!fOut.is_open())
                return false; 

            // Write the array's size to file.
            fOut << m_size;  

            // Write the array to file. ???? 
            fOut.write(m_array, m_size);

            fOut.close();

            return true;
        }

所以,我的问题是当模板类型可以是基本数据类型,结构或类时,如何将数组保存到文件中。我的第一个假设是:

// Write the array to file. ???? 
fOut.write(m_array, m_size);

任何想法都会有所帮助。谢谢。

发现我需要序列化,我重载了运算符&lt;&lt;对于我的Actor类,但希望进一步指导如何将其用于此目的。 Actor有一个我需要保存到文件的std :: string。

std::ofstream & X2D::operator<<(std::ofstream & output, const Actor & p)
{ 
    // insert magical code here 
    return output;  
}

2 个答案:

答案 0 :(得分:0)

考虑让您的save函数成为Array的成员并根据需要重载它。您可能会发现C ++ 11中的std::enable_if功能非常有用,只允许对代码准备好的类型进行序列化。您的

 fOut.write(m_array, m_size);

无法从头开始工作,您需要自己实施。截至撰写本文时,C ++在这方面仍然不是Java。

答案 1 :(得分:0)

这最终成为我的解决方案。重载运算符&lt;&lt;和&gt;&gt;帮助我的课程在保存时保持灵活性。

我会发布下面的代码,以防它对任何人都有用。字符串保存看起来有点混乱,可能会有所改进,但它成功保存/加载长度,然后保存/加载std :: string。

std::ostream& operator<<(std::ostream& os, const Monster& obj)
{  
int length = obj.m_name.length() + 1;  
char buffer[1080];

strcpy_s(buffer, 1080, obj.m_name.c_str());

os << length;
os.write(buffer, strlen(buffer) + 1);
os << endl;

os << obj.m_x << endl;
os << obj.m_y << endl;
os << obj.m_hp << endl;

return os;
 }

 std::istream& operator>>(std::istream& is, Monster& obj)
 { 
int length;
char buffer[1080];  

is >> length;
is.readsome(buffer, length);

std::string sBuffer(buffer, length); 
obj.m_name = sBuffer;

is >> obj.m_x;
is >> obj.m_y;
is >> obj.m_hp;

return is;
 }