C# 登录系统从文本文件错误

本文关键字:文件 错误 文本 登录 系统 | 更新日期: 2023-09-27 18:36:35

好吧,我是编码新手,我知道在SQL中登录更安全,但这只是为了学习streamwriter和reader。

namespace text_file_login
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    private void btn_register_Click(object sender, EventArgs e)
    {
        StreamWriter user_reg = new StreamWriter(@"E:'SSD'Controled Assesment'text file login'text file login'username.txt",true);
        StreamWriter pass_reg = new StreamWriter(@"E:'SSD'Controled Assesment'text file login'text file login'password.txt",true);
        user_reg.WriteLine(textBox1.Text);
        user_reg.Close();
        pass_reg.WriteLine(textBox2.Text);
        pass_reg.Close();
    }
    private void textBox1_TextChanged(object sender, EventArgs e)
    {
    }
    string user = "";
    int txt_position = 0;
    private void btn_login_Click(object sender, EventArgs e)
    {
        StreamReader user_login = new StreamReader(@"E:'SSD'Controled Assesment'text file login'text file login'username.txt", true);
        StreamReader pass_login = new StreamReader(@"E:'SSD'Controled Assesment'text file login'text file login'password.txt", true);
        do
        {
            user = user_login.ReadLine() + "'r'n";
            txt_position++;
        } while (user_login.Peek() != -1);
        string pass = File.ReadLines(@"E:'SSD'Controled Assesment'text file login'text file login'password.txt").Skip(txt_position).Take(1).First();
        if ((pass == textBox2.Text) && (user == textBox1.Text))
        {
            quiz_details form2 = new quiz_details();
            form2.Show();
        }
        else
        {
            // message box
        }
      }
    }
}

好吧,我已经能够在文本文件中写入新行并登录(我认为)我不必检查,因为我不断收到此错误"System.Core 中发生了类型为'System.InvalidOperationException'的未处理异常.dll

附加信息:序列不包含任何元素"

我一直在尝试读取一个文本文件并首先找到用户名,然后在它这样做时停止并保存位置,以便我可以将其输入到跳过中以直接跳到另一个文本文件上的该行,以便找到相应的密码。

有没有办法使这项工作,或者我只是在浪费时间使用这种方法,我完全错了。如果我是,我道歉。我想通过自己制作代码来学习,而不仅仅是复制代码并尝试理解。

C# 登录系统从文本文件错误

错误来自 Skip()。Take()。First() 语句(或者更确切地说,是从哪些值中提供的)

通过进一步拆分你的程序,你可以让它在之后对程序员更加友好(不要在 6 个月内查看代码,然后再次检查:))

更好地组织这些东西的一种方法是(我将其编写为控制台程序,因此您可以将其复制粘贴到新的控制台项目中,它应该可以工作(并向您显示逻辑))

using System;
using System.IO;
namespace RegisterUsers
{
    class Program
    {
        static void AppendToFile(string file, string value)
        {
            using (TextWriter writer = new StreamWriter(file, true))
            {
                writer.WriteLine(value);
            }
        }
        static void Register(string userFile, string passwordFile, string userName, string password)
        {
            AppendToFile(userFile, userName);
            AppendToFile(passwordFile, password);
        }
        static string[] GetLines(string file)
        {
            string[] result = null;
            using (TextReader reader = new StreamReader(file))
            {
                result = reader.ReadToEnd().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
            }
            return result;
        }
        static bool TryLogin(string userFile, string passwordFile, string username, string password)
        {
            string[] userArray = GetLines(userFile);
            int index = -1, length = userArray.Length;
            for (int x = 0; x < length; x++)
            {
                if (string.Equals(userArray[x], username))
                {
                    index = x;
                    break;
                }
            }
            if (index < 0)
            {
                // no username found that matches your requirement
                return false;
            }
            string[] passArray = GetLines(passwordFile);
            if (index > passArray.Length)
            {
                // inconsistency, shouldn't happen...
                return false;
            }
            return string.Equals(passArray[index], password);
        }
        static void Main(string[] args)
        {
            // keep the filenames, don't have to repeat them all the time
            string usernameFile = Path.Combine(Environment.CurrentDirectory, "UserFile.txt");
            string passwordFile = Path.Combine(Environment.CurrentDirectory, "PassFile.txt");
            // register 2 users, one with falsely typed testUser2 as tesetUser2
            Register(usernameFile, passwordFile, "testUser1", "password1");
            Register(usernameFile, passwordFile, "tesetUser2", "password15");
            // try to login with the testUser1 should work
            if (TryLogin(usernameFile, passwordFile, "testUser1", "password1"))
            {
                Console.WriteLine("Login succesfull");
            }
            else
            {
                Console.WriteLine("Login failed!");
            }
            // try to login with testUser2 shouldn't work (now correctly typed)
            if (TryLogin(usernameFile, passwordFile, "testUser2", "password15"))
            {
                Console.WriteLine("Login succesfull");
            }
            else
            {
                Console.WriteLine("Login failed!");
            }
            Console.ReadLine();
        }
    }
}
因此,

您有一个包含用户名的文件和一个包含与这些用户名匹配的密码的文件。当用户单击Login按钮时,您正在尝试从文件中查找他们输入的用户名,找到用户名所在的行,然后在密码文件中查找相应的密码。

让我们暂时忘记这是一种非常糟糕的处理安全性的方式,只是处理试图让代码用于指导目的。

第一个任务是获取匹配用户名的行。我会写一个方法来做到这一点,如下所示:

private int GetUsernameIndex(string username)
{
    //Use a using statement so we don't leave the username.txt file
    //open after we're done reading from it, using will call Dispose for you
    using(var sr = new StreamReader(@"C:'temp'username.txt"))
    {
        string line;
        var index = 0;
        //when sr.ReadLine == null, we've reached the end of the file
        while((line = sr.ReadLine()) != null)
        {
            if(string.Equals(line, username))
                return index;
            index++;
        }
        //Return -1 if username not found
        return -1;
    }
}

此方法将返回用户的索引,如果未找到用户,则返回 -1。我们需要编写的下一个方法是获取密码的方法,它可能看起来像这样:

private string GetPassword(int index)
{
    //Don't bother to search a negative index
    if(index < 0) return string.Empty;
    //Find the line matching the index and return the value there
    using(var sr = new StreamReader(@"C:'temp'password.txt"))
    {
        string line;
        var currentLine = 0;
        while((line = sr.ReadLine()) != null)
        {
            if(index == currentLine)
                return line;
            currentLine++;
        }
        //Return string.Empty if line not found
        return string.Empty;
    }
}

最后,我们将编写一个方法将这两者放在一起并验证用户名和密码:

private bool IsUsernameAndPasswordValid(string username, string password)
{
    var index = GetUsernameIndex(username);
    var storedPassword = GetPassword(index);
    //If storedPassword is empty, then return false
    //If password and storedPassword do not match, then return false
    //Otherwise, the password is valid for this user
    return storedPassword != string.Empty && password == storedPassword; 
}

希望这将帮助您了解文件 I/O 的一些基础知识。同样,您的设计远非理想,但是IMO如果您愿意,知道如何编写该代码会有所帮助。