簡體   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