首页 > 解决方案 > 如何检查用户输入是否已存在于c#中的文本文件中

问题描述

我正在为我的 aa 级计算课程制作 ac# 应用程序。我的课程要求我有一个注册和登录系统,我目前卡在注册部分,因为我的注册系统旨在检查用户选择的用户名是否已经存在于文本文件中。

我已经在解决方案上搜索了堆栈溢出,并尝试实施类似的解决方案,但它似乎不起作用,因为我的代码仍然允许新用户使用已经存在的密码进行注册

 string firstname = txtBoxFirstname.Text;
 string surname = txtBoxSurname.Text;
 string fullname = txtBoxFirstname.Text+" "+txtBoxSurname.Text;
 string username = txtBoxUsername.Text;
 string password = txtBoxPassword.Text;
 string confirmedPassword = txtBoxConfirmedPassword.Text;
 DateTime lastlogin = DateTime.Now;
 bool containsUser = File.ReadLines("users.txt").Contains(username);

if ((!string.IsNullOrEmpty(firstname)) && 
   ((!string.IsNullOrEmpty(surname)) && 
   ((!string.IsNullOrEmpty(username)) && 
   (!string.IsNullOrEmpty(password)) && 
   (!string.IsNullOrEmpty(confirmedPassword)))))
{

    if ((!username.Contains("~")) || (!password.Contains("~")))
    {
        if (password == confirmedPassword)
        {
            if (containsUser == false)//this is the part that check if a username already exists
            {
                FileStream fileStream = new FileStream("users.txt", FileMode.Append, FileAccess.Write);
                StreamWriter streamWriter = new StreamWriter(fileStream);

                try
                {
                    streamWriter.WriteLine(fullname + "~" + username + "~" + password + "~" + lastlogin);

                    MessageBox.Show("User registered successfully", "Registration Successful");

                    this.Hide();
                    var homeForm = new HomeForm();
                    homeForm.Closed += (s, args) => this.Close();
                    homeForm.Show();

                }
                catch (Exception)
                {
                    MessageBox.Show("Error registering the user", "Please try again");
                }
                finally
                {
                    streamWriter.Close();
                    fileStream.Close();
                }
            }
            else
            {
                MessageBox.Show("Sorry this username is already taken", "Please try again");
            }
        }
        else
        {
            MessageBox.Show("Passwords must match",
                        "Incorrect Details");
        }
    }
    else
    {
        MessageBox.Show("Username and password must not contain any special characters i.e. ~", "~ entered");
    }

}
else
{
    MessageBox.Show("Please ensure all data is entered into the fields",
        "Details missing");
}

如果输入的用户名已经存在,我的预期代码应该返回一条消息,说明该用户名已经被使用,但我的程序仍然会为用户创建一个帐户

标签: c#text-files

解决方案


这是一个单行代码,将检查您的文件是否包含用户名:

bool usernameExists = File.ReadAllText(@"C:\path\to\your\file.txt").Contains("~" + username + "~");

你的程序之所以一直注册新用户,是因为你在使用中犯了一个轻微的逻辑错误ReadLines()——它返回一个字符串数组。如果您的文件有 3 行:

John smith~john~password1
Jane smith~jane~password2
Fred smith~fred~password3

这就是你得到的数组,就好像你已经在代码中完成了这个:

var array = new string[3];
array[0] = "John smith~john~password1";
array[1] = "Jane smith~jane~password2";
array[2] = "Fred smith~fred~password3"; 

然后,如果您询问整个数组是否.Contains()为用户名,则只有当数组中的一个字符串恰好是“john”时,它才会响应 true。

该数组没有完全是“john”的字符串,尽管其中一行确实包含文本“john”。但是当您.Contains()在字符串数组上使用时,它只会在其中一个字符串时返回 true在数组中等于“约翰”

数组中的所有字符串都不等于 John

如果你说:

File.ReadLines(...).Contains("John smith~john~password1");

那么结果将是真的,因为数组中的一个字符串确实等于“John smith~john~password1”。

或者,如果您遍历字符串数组并询问每个字符串是否包含“john”:

string[] lines = File.ReadLines(...);
foreach(string line in lines)
  if(line.Contains("~" + username + "~"))
    contains = true;

这也可以解决。

TLDR:

  • ArrayOfString.Contains("john") --> 检查数组中的一个字符串是否等于字符串“john”
  • ASingleString.Contains("john") --> 检查单个字符串中是否有“john”

我知道,可能令人困惑的是,Array 和 String 类都有一个名为 Contains 的方法,但它经常发生 - 名称相同,行为不同


ReadAllText() 之所以有效,是因为它只是将文件作为一个长字符串提供给您。你的用户名总是有一个 ~ 两边,所以一个字符串John smith~john~password1\r\nJane smith~jane~password2\r\nFred smith~fred~password3确实包含~john~

这有一个轻微的错误可能性:如果其中一个密码是“john”,这种方式也将返回 true。当然,为了安全起见,您将对密码进行散列处理以使其无法被读取,对吗?;) 但需要注意并酌情处理是有风险的(稍后)


我很想File.AppendAllText将您的用户名添加到您的文件中,而不是您的操作方式:这是一种打开文件、写入文件并再次关闭文件的单行方法。

您可能想要比我的 File.ReadAllText 更复杂,并采用您的方法,但请记住正确处理字符串数组:

string[] lines = File.ReadLines(...);
foreach(string line in lines){
  string[] bits = line.Split('~');
  string fullname = bits[0];
  string username = bits[1];
  string password = bits[2];
  string lastlogin= bits[3];

  //now you can do more thorough checks
  if(userinput.Equals(username, InvariantCultureIgnoreCase)) //case insensitive compare
}

将 ~ 上的字符串拆分为其组件是检查数据的一种更可靠的方法,这将有助于稍后检查他们输入了正确的密码,返回他们的全名以获取欢迎消息等。


推荐阅读