사용자 정보를 저장하기 위해 파일에 저장되는 User 클래스가있는 프로그램을 작성했습니다. 그러나 여러 사용자가있을 수 있으므로 파일을 단일 사용자로 저장하는 대신 사용자 목록입니다. 이것은 XNA에 있으므로 게임이지만 실제로 사물에 영향을 미치지 않아야합니다. 사용자는 코인, 스킨, 인벤토리, 사용자 이름, 암호 (있는 경우) 및 hasPassword 부울을 가지고 있습니다. 사용자가 코인을 가지고 있기 때문에 편집 가능한 텍스트 파일이 아니기 때문에 바이너리 파일로 저장했습니다. 몇 가지 코드를 작성하고 테스트 한 결과 여러 사용자를 목록에 저장하려고 할 때까지 모든 것이 훌륭하고 멋졌습니다. 어떤 이유로 두 번째 사용자를 저장하고 목록을 읽을 때마다 목록에는 하나의 개체 (첫 번째 사용자) 만있었습니다. 여기에서는 이해하기 쉽도록 코드와 예제를 제공합니다.
[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 위로 마우스를 가져 갔지만 표시되는 유일한 사용자는 Bob이었고 Joe는 존재하지 않았습니다. 어떤 아이디어? 또한 : 저는 열세 살입니다. 오랫동안 프로그래밍하지 않았기 때문에 사용하는 모든 용어를 이해하지 못할 수도 있습니다. 미리 감사드립니다!
문제는 사용자 목록을 저장할 때을 열고 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);
그만한 가치가 있기 때문에 이것은 사용자를 저장하고로드 하는 데 매우 비효율적 인 방법입니다. 기본적으로 모든 사용자의 변경 사항에 대해 전체 목록을 읽고 작성합니다. 또한 스레드로부터 안전하지 않습니다 (즉, 여러 동시 업데이트가있는 멀티 플레이어 게임 인 경우 파일을 여는 방법과 어떤 업데이트가 발생하는지에 따라 사용자 파일이 손상 될 수 있음). 일반 파일이 아닌 적절한 데이터베이스를 조사 할 수 있습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다