c++将对象写入和读取到二进制文件中

c++ writing and reading objects to binary files

本文关键字:读取 二进制文件 对象 c++      更新时间:2023-10-16

我正在尝试读取一个数组对象(array是我使用读写函数从二进制文件中读写的一个类。到目前为止,写函数可以工作,但由于某些原因无法正确读取文件。这就是写函数:

void writeToBinFile(const char* path) const
    {
        ofstream ofs(path, ios_base::out | ios_base::app | ios_base::binary);
        if (ofs.is_open())
        {
            ostringstream oss;
            for (unsigned int i = 0; i < m_size; i++)
            {
                oss << ' ';
                oss << m_data[i];
            }
            ofs.write(oss.str().c_str(), oss.str().size());
        }
    }

这是读取功能:

void readFromBinFile(const char* path)
    {
        ifstream ifs(path, ios_base::in | ios_base::binary || ios_base::ate);
        if (ifs.is_open())
        {
            stringstream ss;
            int charCount = 0, spaceCount = 0;
            ifs.unget();
            while (spaceCount != m_size)
            {
                charCount++;
                if (ifs.peek() == ' ')
                {
                    spaceCount++;
                }
                ifs.unget();
            }
            ifs.get();
            char* ch = new char[sizeof(char) * charCount];
            ifs.read(ch, sizeof(char) * charCount);
            ss << ch;
            delete[] ch;
            for (unsigned int i = 0; i < m_size; i++)
            {
                ss >> m_data[i];
                m_elementCount++;
            }
        }
    }

这些是类字段:

T* m_data;
unsigned int m_size;
unsigned int m_elementCount;

我使用以下代码进行写入和读取(1次执行用于读取另一次执行用于写入):

Array<int> arr3(5);
    //arr3[0] = 38;
    //arr3[1] = 22;
    //arr3[2] = 55;
    //arr3[3] = 7;
    //arr3[4] = 94;
    //arr3.writeToBinFile("binfile.bin");
    arr3.readFromBinFile("binfile.bin");
    for (unsigned int i = 0; i < arr3.elementCount(); i++)
    {
        cout << "arr3[" << i << "] = " << arr3[i] << endl;
    }

现在问题出在readFromBinFile函数上,它陷入了一个无限循环,peek()由于某种原因返回-1,我不知道为什么。还要注意的是,我在二进制文件中使用空格在每个元素之间形成屏障,这样我就知道要区分数组中的对象,也知道在写入开始时使用空格在文件中以前存储的二进制数据和数组二进制数据之间形成屏障。

在我看来,主要的问题是用可变大小的文本形式编写固定大小的二进制数据。如果你坚持纯二进制形式,它可能会简单得多。

不需要先写入字符串流,然后再将输出写入实际文件,只需将二进制数据直接写入文件即可:

ofs.write(reinterpret_cast<char*>(m_data), sizeof(m_data[0]) * m_size);

然后在读取数据时执行类似的操作。

<小时>

为了实现这一点,您当然需要在写入实际数据之前先保存数组/向量中的条目数量。

因此,实际的写入功能可以像一样简单

void writeToBinFile(const char* path) const
{
    ofstream ofs(path, ios_base::out | ios_base::binary);
    if (ofs)
    {
        ofs.write(reinterpret_cast<const char*>(&m_size), sizeof(m_size));
        ofs.write(reinterpret_cast<const char*>(&m_data[0]), sizeof(m_data[0]) * m_size);
    }
}

以及读取功能

void readFromBinFile(const char* path)
{
    ifstream ifs(path, ios_base::in | ios_base::binary);
    if (ifs)
    {
        // Read the size
        ifs.read(reinterpret_cast<char*>(&m_size), sizeof(m_size));
        // Read all the data
        ifs.read(reinterpret_cast<char*>(&m_data[0]), sizeof(m_data[0]) * m_size);
    }
}

根据定义m_data的方式,在读取实际数据之前,可能需要为其分配内存。

<小时>

哦,如果你想在数组的末尾附加数据(但为什么在你显示的当前代码中,你无论如何都要重写整个数组),你可以在开头写大小,搜索到末尾,然后写新数据。