I am currently working on a school project that will have your classic log-in/register form. The project requires that we include a binary file to 'securely' store each User's information e.g username, password etc.
I am successfully writing new user's information to a binary file named "users" when they register, and then I am successfully reading it back to a rich text box. (This is simply so I know that everything is being read back).
I am also able to successfully recognise the last registered user when this user is inputted to the Log-In section of the form, but I cannot recognise any other user's information.
My code for the Register (e.g when the registry button is clicked)
private void btnRegister_Click(object sender, EventArgs e)
{
//Try - Catch Statements
//Try to set the forename
try
{
newUser.Forename = txtForename.Text;
errForename.Icon = Properties.Resources.CorrectIcon;
errForename.SetError(txtForename, "OK");
}
// catch the exception error if one is raised and place the message
//into the ErrorProvider
catch (NewException exc)
{
errForename.SetError(txtForename, exc.MessageM);
}
//Try to set the surname
try
{
newUser.Surname = txtSurname.Text;
errSurname.Icon = Properties.Resources.CorrectIcon;
errSurname.SetError(txtSurname, "OK");
}
// catch the exception error if one is raised and place the message
//into the ErrorProvider
catch (NewException exc)
{
errSurname.SetError(txtSurname, exc.MessageM);
}
//Try to set the password
try
{
newUser.Password = txtPasswordR.Text;
errPasswordR.Icon = Properties.Resources.CorrectIcon;
errPasswordR.SetError(txtPasswordR, "OK");
}
// catch the exception error if one is raised and place the message
//into the ErrorProvider
catch (NewException exc)
{
errPasswordR.SetError(txtPasswordR, exc.MessageM);
}
// These lines of code set the User class
if (newUser.Password != null )
{
newUser.Forename = txtForename.Text;
newUser.Surname = txtSurname.Text;
newUser.Username = txtUsernameR.Text;
newUser.Password = txtPasswordR.Text;
FileStream fileStream = new FileStream("../../Textfiles/users.bin", FileMode.Append);
BinaryWriter binaryWriter = new BinaryWriter(fileStream);
{
binaryWriter.Write(newUser.Forename);
binaryWriter.Write(newUser.Surname);
binaryWriter.Write(newUser.Username);
binaryWriter.Write(newUser.Password);
}
binaryWriter.Flush();
binaryWriter.Close();
}
}
My Code for Reading from the Bin file
public bool ReadFromBin(string a, string b)
{
bool okFlag = false;
FileStream fileStream = File.OpenRead("../../TextFiles/users.bin");
BinaryReader binaryReader = new BinaryReader(fileStream);
while (binaryReader.PeekChar() != -1)
{
newUser.Forename = binaryReader.ReadString();
newUser.Surname = binaryReader.ReadString();
newUser.Username = binaryReader.ReadString();
newUser.Password = binaryReader.ReadString();
if ((newUser.Username == a) && (newUser.Password == b))
okFlag = true;
else
okFlag = false;
}
binaryReader.Close();
return okFlag;
}
And finally the very simple code for the Log-in
private void btnLogIn_Click(object sender, EventArgs e)
{
if(this.ReadFromBin(txtUsername.Text, txtPassword.Text) == false)
{
MessageBox.Show("Not registered!");
}
else
{
MessageBox.Show("Registered!");
Game frm = new Game(newUser);
frm.Show();
}
}
My understanding is that the problem is most likely in the while loop contained within the ReadFromBin method, I am just unsure of how to fix it. Thanks!
This is the problem:
if ((newUser.Username == a) && (newUser.Password == b))
okFlag = true;
else
okFlag = false;
That code is run for every entry in the file. So if the okFlag
is set to true
from the first entry, but there are other entries, then it's irrelevant - because it'll be set to false
for the other entries.
The simplest fix to this is to use a using
statement for the FileStream
and BinaryReader
so you don't need the Close
call, and then just remove the okFlag
entirely, just returning true
if you encounter an entry which matches:
if (newUser.Username == a && newUser.Password == b)
{
return true;
}
Then put a return false
after the loop, so you only return false if no entries match.
Of course, you really shouldn't be putting passwords in a file anyway, but that's a different issue...
Note that there are more reasons for a using
statement than just to fix this issue - you want to close the stream and reader even if an exception is thrown. You should always use a using
statement for scenarios like this, where you're opening a resource, using it, and then closing it - you want to make the close operation happen regardless of whether an exception is thrown while you're using the resource.
See more on this question at Stackoverflow