2011-08-23 65 views
1

我在C++中使用VS2010。部分寫入文件 - C++

我有一堂課名爲Room。房間有一個x和一個y屬性,然後是一堆其他屬性。

我有一個名爲Rooms.txt的文件,它包含一堆'房間'對象的屬性。它使用了自定義的語法,這樣一個條目可能是這樣的:

$ X $ Y $名稱$大小$類型$狀態$ EOL @ $

所以,我得到了以下工作正常:在播放器輸入X和Y座標,並將文本文件中相應條目的值提供給Room對象。

然後我想要做的是允許玩家更改這些變量中的一些並將它們寫回文件,但我無法弄清楚如何。這是我迄今爲止的最大努力:

ifstream inRoom; 
ofstream outRoom; 
string path = saveRoot; 
path.append(ModLoad); // the last two lines get the path for the file to be read/written 

inRoom.open(path); 
//outRoom.open(path); 
string temp; 
string temp2; 
if(inRoom.bad()){ 
    cout << "ERROR: Bad save!"; 
} 
while(inRoom.good()){ 
    temp2 = temp; 
    getline(inRoom,temp,'$'); 
    cout << temp <<inRoom.tellg(); 
    if ((atoi(temp2.c_str())==myPlayer.X)&&(atoi(temp.c_str())==myPlayer.Y)){ 
     int seek = inRoom.tellg(); 
     inRoom.close(); 
     cout << "Opening " << path << "for writing \n"; 
     outRoom.open(path); 
     outRoom.seekp(seek); 
     outRoom.write("HELLO!", 6); 
     outRoom.close(); 
    } 
} 
inRoom.close(); 

此外,我需要覆蓋的值,而不是插入新的數據。有什麼想法嗎?

回答

1

您選擇了錯誤的格式。要覆蓋工作,您需要一個固定寬度格式。因此,無論如何,每個房間在文件中都佔用相同的字節數。通過這種方式,當您覆蓋一個房間時,您可以將新房間放在舊房間的頂部,而不必擔心是否需要插入幾個字節或從文件中刪除幾個字節。

如果您有一個公式可以直接從x和y座標中指定文件中某個房間的位置,那麼它的確會讓您的生活更輕鬆。不必循環查看文件尋找合適的房間,您可以立即尋找合適的位置。

+0

如果你的「區域」是從疏到XY一個seekpos公式可能會非常棘手。如果區域很稀疏,我會使用排序的跳轉表開始文件。 –

0

重寫只在一個文件中的一些數據,需要兩兩件事:

  • 你必須知道文件從哪裏開始寫作中的位置。然後你可以像使用seekp()那樣去那個位置。
  • 更棘手的是:寫入的數據必須是相同的字節數。否則,您將覆蓋以下數據或使一些舊字節與您的文件結構混淆。

要打開改寫文件部分使用

file.open(filename, ios::binary|ios::in|ios::out|ios::ate); 
file.seekg(0); 
// or go to the position to read your data directly 
// store that position using tellg() 
// read data 
// restore position using tellp() 
// write data (in exact same length) 

我記得這裏的關鍵是要打開的文件在其結束ios::ate。否則,您可能(部分)丟失文件的內容。

0

請記住,您使用的是C++,因此您必須考慮對象。我會做的是:

  • 超載到你的房間添加類系列化>>和< <運營商
  • 閱讀條目列表到內存(使用,例如,標準::向量)在執行開始
  • 當用戶輸入X和Y,存儲在內存,如果用戶修改的東西顯示出來
  • ,用新
  • 替換內存中的現有條目條目列表中查找corresponging進入
  • 將整個條目列表寫回該文件完全替換其內容

這裏有一個快速和骯髒的準則草案只是爲了顯示這個想法:

#include <vector> 
#include <iostream> 
#include <fstream> 
#include <iterator> 

class Room 
{ 
    public: 
     int x; 
     int y; 
     std::string a; 
     std::string b; 

    private: 
     friend std::ostream& operator <<(std::ostream& os, const Room& r); 
     friend std::istream& operator >>(std::istream& is, Room& r); 

}; 

std::ostream& operator <<(std::ostream &os, const Room& r) 
{ 
    return os << r.x << r.y << r.a << r.b; 
} 

std::istream& operator >>(std::istream& is, Room& r) 
{ 
    return is >> r.x >> r.y >> r.a >> r.b; 
} 


int main() 
{ 
    std::vector<Room> roomList; 

    // read the list 
    ifstream in("out.txt"); 
    istream_iterator<Room> ii(in), iieof; 
    copy(ii, iieof, back_inserter(roomList)); 
    in.close(); 

    // do something with your data 
    // ... 

    // save the modified list back 
    ofstream out("out.txt"); 
    ostream_iterator<Room> oi(out, "\n"); 
    copy(roomList.begin(), roomList.end(), oi); 
    out.close(); 

    return 0;  
}