繁体   English   中英

向二进制文件写入/读取std :: set <T>

[英]Write/read std::set< T > to/from binary file

我正在尝试编写一对写入/读取函数,分别用于将std::set< T >数据容器存储到二进制文件中/从二进制文件中检索数据。 我的writeSet()函数似乎可以正常工作,并存储std::set< T >数据容器,而没有任何明显的问题。 但是, readSet()函数不会,并且会抛出“未处理的异常访问冲突读取位置0xFEEEFEF6”。 main()函数返回EXIT_SUCCESS之后发生异常。

就我所能调试的(使用Visual Studio 2013)而言, readSet()实际上确实可以成功读取二进制文件并将数据正确分配给所寻址的std::set< T >数据容器。 VS2013崩溃时,它为我提供了中断程序执行的机会,并指出xtree.h头文件中的错误。 具体地说,调试器抱怨_Pnext|| _Ptr != 0 && (*_Pnext)->_Ptr != _Ptr) || _Ptr != 0 && (*_Pnext)->_Ptr != _Ptr)

 #if _ITERATOR_DEBUG_LEVEL == 2
    void _Orphan_ptr(_Myt& _Cont, _Nodeptr _Ptr) const
        {   // orphan iterators with specified node pointers
        _Lockit _Lock(_LOCK_DEBUG);
        const_iterator **_Pnext = (const_iterator **)_Cont._Getpfirst();
        if (_Pnext != 0)
            while (*_Pnext != 0)
                if ((*_Pnext)->_Ptr == this->_Myhead
                    || _Ptr != 0 && (*_Pnext)->_Ptr != _Ptr)
                    _Pnext = (const_iterator **)(*_Pnext)->_Getpnext();
                else
                    {   // orphan the iterator
                    (*_Pnext)->_Clrcont();
                    *_Pnext = *(const_iterator **)(*_Pnext)->_Getpnext();
                    }  

我的最小工作解决方案如下:

writeSet() :将std :: set <T>写入二进制文件

template < class T >
void writeSet(const std::string& filePath, const std::string fileName, std::set<T>& data)
{
    // Construct binary file location string using filePath and fileName inputs
    std::stringstream file; file << filePath.c_str() << "/" << fileName.c_str();
    std::ofstream fileStream; fileStream.open(file.str().c_str(), std::ios::out | std::ios::binary); 

    // First write number of std::set elements held by data, and then write std::set block to binary file
    std::set<T>::size_type n = data.size(); 
    fileStream.write(reinterpret_cast<char*>(&n), sizeof(std::set<T>::size_type));
    fileStream.write(reinterpret_cast<char*>(&data), sizeof(T)*n); 
    fileStream.close();
}

readSet() :从二进制文件读取std :: set <T>

template < class T >
void readSet(const std::string& filePath, const std::string fileName, std::set<T>& data)
{
    // Construct binary file location string using filePath and fileName inputs
    std::stringstream file; file << filePath.c_str() << "/" << fileName.c_str();
    std::ifstream fileStream; fileStream.open(file.str().c_str(), std::ios::in | std::ios::binary); 


    // First read number of elements stored in binary file, then write file content to adresses std::set data variable
    std::set<T>::size_type n; 
    fileStream.read(reinterpret_cast<char*>(&n), sizeof(std::set<T>::size_type));
    fileStream.read(reinterpret_cast<char*>(&data), sizeof(T)*n); 
    fileStream.close();
}

main() :最小的main函数,该函数再现“未处理的异常”错误

#include <fstream>
#include <iostream>
#include <set>
#include <sstream>
#include <string>

int main()
{
    // Define binary file read/write directory
    const std::string path("C:/data");

    // writeSet() testing...
    std::set<int> writeSetData;
    writeSetData.insert(1); writeSetData.insert(3);
    writeSetData.insert(0); writeSetData.insert(2);

    writeSet(path, "binaryFile", writeSetData);

    // readSet() testing...
    std::set<int> readSetData;
    readSet(path, "binaryFile", readSetData);

    std::cout << "readSetData= {";
    for (std::set<int>::iterator it = readSetData.begin(); it != readSetData.end(); ++it){
        std::cout << *it << ", ";
    } std::cout << "}" << std::endl;

    return EXIT_SUCCESS;
}

是您所有的T POD吗? 否则,制作二进制副本几乎没有意义,而不是创建语义副本。
此外,数据集管理被保存在由管理动态分配的内存set ,而不是在set本身。
第三点,当您尝试在其中写入任意数量的元素时,该空间不会神奇地增长或缩小。
您必须要求通过手动插入元素来扩大集合!

附带说明一下, std::string对于字符串连接而言工作得很好,不需要拆散std::stringstream

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM