2016-07-24 141 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

感谢您的回答;它现在有效。另外,感谢您的建议;我想使用一个数据库,但我还没有达到那个水平。 –