C# 创建一个 Class List<>/Dictionary<>,作为数据库写入和读取 .txt 文件而不覆盖数据

C# Creating a Class List<>/Dictionary<>, writing to and reading from .txt file as a database without overwriting data

这是你们在这里遇到的最常见的问题之一,所以请原谅我,但无论我如何努力搜索,我都无法解决这个问题。

我正在为 Windows Forms Application 中的项目构建一个钥匙串应用程序,为了尽可能容易地理解这个概念,我使用了 List<> 而不是 Dictionary//iList

这是我一直在使用的Class:

public class Account
{
    public static List<Account> myAccountList = new List<Account>();
    public string Domain; //this is supposed to be google/skype/facebook
    public string Email;
    public string Username;
    public string Password;

    public Account (string domain, string email, string username, string password)
    {
        Domain = domain;
        Email = email;
        Username = username;
        Password = password;
        myAccountList.Add(new Account(domain, email, username, password)); //constructor calls the new list instance
    }
    private static void SaveToFile()
    {
        System.IO.File.WriteAllLines(@accountdb.txt, myAccountList);
    }
    private static void ReadFromFile() // this is meant to be used as authentication in my main form, it isn't necessary right now..
    {
        System.IO.File.ReadAllLines(@accountdb.txt);
    }
}

我有几个问题:

  1. 我无法创建功能性保存方法来写入文件,我在 System.IO
  2. 中尝试了几种方法
  3. 当我把列表改成一维数组时,它会不断覆盖,我想模拟一下MySQL,以便以后熟悉。

调用构造函数的按钮点击事件:

private void buttonSave_Click(object sender, EventArgs e)
    {
        string domain, email, username, password;
        domain = comboboxDomain.Text;
        email = textboxEmail.Text;
        username = textboxUsername.Text;
        password = textboxPassword.Text;
        //Checking for correct EMAIL

        if (!textboxEmail.Text.Contains("@") && (!textboxEmail.Text.Contains(".")))
        {
            MessageBox.Show("Invalid Email Format");
        }
        else
        {
            Account account = new Account(domain, email, username, password);
        }
    }

根据您的评论,您似乎想要 append 而不是 write。如果你想附加到一个文件(即添加到已经存在的内容),你需要使用 AppendAllLines() 函数。

但是您遇到了更大的问题,因为您正在尝试将对象列表而不是字符串写入您的文件。如果你只想写密码,你需要这个:

private static void SaveToFile()
{
    System.IO.File.AppendAllLines("path/to/file", myAccountList.Select(x => x.Password));
}

如果文件存在,此方法将追加到文件,如果不存在,则创建一个新文件。

文档here

WriteAllLines 期望 string[] 作为第二个参数。因此,您需要创建一种方法来将单个 Account 对象表示为字符串。最简单的方法是覆盖 ToString 方法。然后使用 Linq Select 方法来 select 它们。

此外,如果 Account class 不包含帐户列表会更好。那真的应该是一个单独的class。尝试这样的事情:

void Main()
{
    var accountList = new AccountList();

    //Save a few accounts to the file
    Account a1 = new Account("Google", "GoogleEmail", "GoogleUser", "GooglePass");
    accountList.Add(a1);
    Account a2 = new Account("Netflix", "NetflixEmail", "NetflixUser", "NetflixPass");
    accountList.Add(a2);

    AccountList.SaveToFile(@"g:\test\accounts.txt", accountList);


    //Load the accounts from the file
    AccountList aList2 = AccountList.ReadFromFile(@"g:\test\accounts.txt");
    aList2.Dump();
}

public class AccountList
{
    private List<Account> accounts;
    public IEnumerable<Account> Accounts { get { return accounts;} }

    public AccountList()
    {
        this.accounts = new List<Account>();
    }

    public void Add(Account a)
    {
        accounts.Add(a);
    }

    public static void SaveToFile(string filename, AccountList accounts)
    {
        //Selects all the `Account` instances and creates a string[]
        System.IO.File.WriteAllLines(filename, accounts.Accounts.Select(a => $"{a}").ToArray());
    }

    public static AccountList ReadFromFile(string filename) // this is meant to be used as authentication in my main form, it isn't necessary right now..
    {
        var result = new AccountList();

        //Read each line from the file and create an Account instance.
        foreach (var line in System.IO.File.ReadAllLines(filename))
        {
            if (!string.IsNullOrWhiteSpace(line))
            {
                var parts = line.Split(',');
                if (parts.Length == 4)
                {
                    Account a = new Account(parts[0], parts[1], parts[2], parts[3]);
                    result.Add(a);
                }
            }
        }

        return result;
    }
}

public class Account
{
    public string Domain; //this is supposed to be google/skype/facebook
    public string Email;
    public string Username;
    public string Password;

    public Account(string domain, string email, string username, string password)
    {
        Domain = domain;
        Email = email;
        Username = username;
        Password = password;
    }

    public override string ToString()
    {
        return $"{Domain},{Email},{Username},{Password}";
    }
}