2014-01-20 145 views
0

我是C++初學者,我想要做的是讀寫我在程序中創建的Staff對象。將C++對象讀取和寫入隨機訪問文件

下面是我寫的方法:

void Staff::writeStaffFile(){ 
const int vectorSize = staffList.size(); 
ofstream staffDetailsFile("staffDetails.txt", ios::out | ios::binary); 
if (!staffDetailsFile){ 
    cerr << "\nFile open error - Error writing staff details" << endl; 
    return; 
    } 

for (int i=0; i<vectorSize; i++){ 
    staffDetailsFile.write(reinterpret_cast< const char* >(&staffList[i]), sizeof(Staff)); 
    } 
staffDetailsFile.close(); 
} 

員工對象都保存在一個載體,在這裏我想保存所有的工作人員在載體導入文件對象可用。它工作並將數據寫入文件。

我出錯的地方是讀取文件。這是我的閱讀方法:

void Staff::readStaffFile(){ 
ifstream staffDetailsFile("staffDetails.txt", ios::in | ios::binary); 
if (!staffDetailsFile) 
    cerr << "\nFile open error - Staff details not found" << endl; 
else { 
    Staff *temp = (Staff *)malloc(sizeof(Staff)); 
    while(!staffDetailsFile.eof()){ 
     staffDetailsFile.read(reinterpret_cast<char *>(temp),sizeof(Staff)); 
     if (temp != NULL) 
      Staff::insertAccount(temp); 
     } 
    } 
} 

當我運行這部分時,在Visual Studio中出現以下錯誤。

未處理的異常在0x53950E9A(msvcr110d.dll)在StaffPersonnelSystem.exe:0000005:訪問衝突讀取位置0x00F5BF28。

我似乎無法理解我出錯的地方,如果有人能幫我解決這個問題,我會非常感激。

PS:這是我的工作人員類定義:

#include <iostream> 
#include <string> 
#include <malloc> 
#include <vector> 
#include "Person.h" 

#ifndef STAFF_H 
#define STAFF_H 

class Staff : public Person { 

public: 
    Staff(int const, string,string,int,string,string,char,Designation,Department,Date,string,string,Date,bool); //staff constructor 

    //set methods 
    void setStaffIDNumber(int const); 
    void setUsername(string); 
    void setPassword(string); 
    void setAccessLevel(int); 


    //edit, modify other staff accounts 
    static void addStaff(int); 
    static int generateStaffID(); 
    static void deleteStaff(int, Staff*); 
    static void changePassword(Staff*); 
    static bool modifyStaff(int, Staff*); 
    static void insertAccount(Staff*); 
    static void printStaffDetails(Staff*); 
    static void writeStaffFile(); 
    static void readStaffFile(); 
    static bool isValidAccount(Staff*,string, string); 
    static Staff* chooseStaffAccount(); 
    static void searchStaff(); 
    static void refreshVector(); 

    //get methods 
    Staff getStaffAccount(string); 
    int getAccessLevel(); 
    string getUserName(); 
    int getStaffID(); 
    string getPassword(); 

    //search staff accounts 
    static Staff* searchStaffAccount(string); //search staff accounts by userName 
    static Staff* searchByID(int); //search staff accounts by ID 
    static void searchByDept(Department); //Get staff registered to perticular department 
    static void searchByDesignation(Designation); //Get staff registered to perticular designation 
    static void sortVector(); 
    static bool sortByID(Staff &lhs, Staff &rhs); 
    static bool isVectorEmpty(); 

private: 
    int staffIDNumber; 
    string userName; 
    string passWord; 
    int accessLevel; 

    }; 

#endif 
+0

向我們展示員工類定義。 –

+0

序列化和反序列化的常用方法是爲您的類重載插入/提取操作符以接受並返回ostream&/ istream&,然後在這些方法中調用各個數據成員的插入/提取操作符。只有當你的所有數據成員都是基元而不是指針或引用時,memcpy才能工作。在你的情況下,你有兩個字符串數據成員(userName和passWord),它們將char數組存儲在對象之外,並保存爲指向緩衝區的指針。 (忽略當前SSO的任何影響)。 – rakeshdn

+0

編寫一個[最小示例],編譯(編譯),編譯(編譯),編譯在調試模式下使用調試器。作爲一名程序員,您只需花費10%的時間編寫代碼,90%的時間調試它。 – Drop

回答

0

你犯了幾個錯誤。首先是認爲你 可以做任何事情與一個按位圖像寫入文件。 全部 程序之外的數據必須以某種方式進行格式化。如果您要 想要二進制格式,則需要格式化和解析 和intstring的函數。 (除非有一些強有力的理由 這樣做,否則,你應該使用現有的格式:XDR 可能是最簡單的。)

如果你的數據是所有的基本數據類型(intchar[]等), 寫作並閱讀按位圖像可能會好像 工作。直到您更改了編譯器選項或版本,或者嘗試使用其他系統 。即使是基本類型也需要格式化。 (當然 ,與指針有什麼需要格式化; std::string幾乎可以肯定在其 實現指針。)

最後:您使用的staffDetailsFile.read 結果沒有測試讀取成功與否。這是 未定義的行爲。你的循環可能應該是while (staffDetailsFile.read(...))。 (但這隻會讓你的 未格式化的緩衝區,你仍然需要提取數據。 而且很可能你甚至不知道要讀取多少字節,因爲你的std::string格式可能有一個變量 長度。)

0

不能寫入文件的工作人員類型的對象,讀取它,並希望它會成功。這種事情只有在你的班級有POD(普通舊數據)時纔有可能。您的員工類不是POD - 它包含字符串對象。 順便說一句,你的測試if (temp != NULL)是錯誤的 - 如果在讀取調用之前temp不是NULL,它在它之後不會是NULL。

+0

即使它是POD,如果以後使用不同的選項編譯,或者使用不同版本的編譯器,也不能期望讀回它。 –