2016-07-24 102 views
3

我編寫了一個程序,該程序具有一個用戶類,該用戶類保存到文件以存儲用戶信息。但是,可以有多個不同的用戶,因此不是將該文件保存爲單個用戶,而是用戶列表。這是XNA,因此是一款遊戲,但這不應該對事物產生任何影響。用戶有硬幣,皮膚,他們的庫存,他們的用戶名,他們的密碼(如果他們有一個)和一個hasPassword布爾。因爲用戶有硬幣,我不希望這是一個可編輯的文本文件,所以我將它保存爲二進制文件。我編寫了一些代碼,對它進行了測試,並且一切都很好,並且很花哨,直到我試圖將多個用戶保存到列表中。出於某種原因,每當我保存第二個用戶並在列表中讀取時,該列表只有一個對象(第一個用戶)。在這裏,我將提供的代碼和一個例子來說明這更容易理解:C#:向二進制文件寫入和讀取列表

[Serializable] 
class User 
{ 
    #region Fields & Properties 

    public string Username = ""; 
    public string Password = ""; 
    public bool HasPassword = false; 

    public int Coins = 0; 
    public List<Achievement> AchievementsCompleted = new List<Achievement>(); 
    public List<InventoryItem> Inventory = new List<InventoryItem>(); 
    public List<string> Skins = new List<string>(); 

    public string CurrentSkinAsset { get; set; } 

    const int SPACING = 10; 

    const string FILE_PATH = "Users.bin"; 

    #endregion 

    #region Constructors 

    public User(string username, int coins, string skinPath, ContentManager content) 
    { 
     Username = username; 
     CurrentSkinAsset = skinPath; 
    } 
    public User(string username, string password, int coins, string skinPath, ContentManager content) 
     : this(username, coins, skinPath, content) 
    { 
     HasPassword = true; 
     Password = password; 
    } 

    #endregion 

    #region Public Methods 

    public static List<User> LoadUsers() 
    { 
     FileStream fileStream = null; 
     List<User> returnList = null; 
     try 
     { 
      if (File.Exists(FILE_PATH)) 
      { 
       fileStream = new FileStream(FILE_PATH, FileMode.Open, FileAccess.Read); 
       BinaryFormatter deserializer = new BinaryFormatter(); 
       returnList = (List<User>)deserializer.Deserialize(fileStream); 
      } 
      else 
      { 
       fileStream = File.Create(FILE_PATH); 
       List<User> users = new List<User>(); 
       BinaryFormatter serializer = new BinaryFormatter(); 
       serializer.Serialize(fileStream, users); 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("There's been an error. Here is the message: " + e.Message); 
     } 
     finally 
     { 
      if (fileStream != null) 
      { 
       fileStream.Close(); 
      } 
     } 

     return returnList; 
    } 

    public void SerializeUser() 
    { 
     // Also works 
     FileStream fileStream = null; 
     List<User> users; 
     BinaryFormatter binaryFormatter = new BinaryFormatter(); 
     try 
     { 
      if (File.Exists(FILE_PATH)) 
      { 
       fileStream = File.Open(FILE_PATH, FileMode.Open); 
       //fileStream = new FileStream(FILE_PATH, FileMode.Open, FileAccess.ReadWrite); 
       users = (List<User>)binaryFormatter.Deserialize(fileStream); 
      } 
      else 
      { 
       fileStream = File.Create(FILE_PATH); 
       users = new List<User>(); 
      } 

      for (int i = 0; i < users.Count; i++) 
      { 
       if (users[i].Username.ToLower() == this.Username.ToLower()) 
       { 
        users.Remove(users[i]); 
       } 
      } 
      users.Add(this); 
      binaryFormatter.Serialize(fileStream, users); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("There's been an error. Here is the message: " + e.Message); 
     } 
     finally 
     { 
      if (fileStream != null) 
      { 
       fileStream.Close(); 
      } 
     } 
    } 

    #endregion 
} 

下面是測試代碼我寫的(在的Game1 LoadContent方法):

User test = new User("Bob", 0, "skin1", Content) 
test.SerializeUser(); 

我在看Debug文件夾並找到一個名爲「Users.bin」的新文件。它有一堆隨機字符,如預期的那樣。我將測試的用戶名參數從「Bob」更改爲「Joe」,應該添加一個新用戶。但是...

這裏的讀取用戶代碼:

List<User> testList = User.LoadUsers(); 

我在下一行代碼插入一個斷點,懸停testList,但唯一可見的用戶是鮑勃,喬不存在。有任何想法嗎? 另外:我十三歲。我可能不瞭解你使用的所有術語,因爲我沒有爲超長時間編程。 在此先感謝!

+1

與你的問題並不真正相關,但你可能想看看[MonoGame](http://www.monogame.net/)。微軟在幾年前停止了XNA Framework的開發,但MonoGame是XNA Framework 4的一個積極開發的開源實現。與XNA不同,它還支持Android,iOS,Linux,OS X,PS4等平臺。祝您好運! – hankide

+0

謝謝,從來沒有注意到這一點。以爲MonoGame是Xna的Mac版本或其他。 –

回答

3

的問題是,當你保存你的用戶,你要打開的FileStream,列表中的閱讀列表(以取代目前的用戶),然後保存新的列表到FileStream而不復位位置。初始讀取將FileStream前移到文件末尾 - 保存然後將新列表追加到初始列表之後的FileStream中。

會發生什麼事,然後就是你有一個看起來像這樣的文件:每次你讀它的時候

*start of file* 
List(User1) 
List(User1,User2) 
*end of file* 

和,你只得到那個初步名單。

試試這個:

 users.Add(this); 
     filStream.Position = 0; 
     binaryFormatter.Serialize(fileStream, users); 

對於它的價值,這是對付保存和載入您的用戶非常低效的方法。您基本上正在閱讀和編寫整個列表,以便對任何用戶進行更改。它也不是線程安全的(這意味着如果這是一個多人同時更新的遊戲,你可能會在你的用戶文件中發生損壞,這取決於你打開它以及發生什麼更新)。您可能想要查看一個合適的數據庫而不是純文件。

+0

感謝您的回答;它現在有效。另外,感謝您的建議;我想使用一個數據庫,但我還沒有達到那個水平。 –