简体   繁体   English

C#创建一个类列表<> / Dictionary <>,作为数据库写入.txt文件并从中读取,而不会覆盖数据

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

This is one of the most common questions you guys get here so forgive me but I cannot get past this no matter how hard I search. 这是你们到这里来最常见的问题之一,请原谅我,但是无论我怎么努力搜寻,我都无法克服。

I am building a keychain application for a project in Windows Forms Application, and for the purpose of understanding this concept as easily as possible I went with a List<> rather than Dictionary//iList 我正在为Windows Forms Application中的项目构建钥匙串应用程序,为了尽可能容易地理解此概念,我使用List <>而不是Dictionary // iList

This is the Class I have been using: 这是我一直在使用的类:

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);
    }
}

I have a couple issues with this: 我对此有几个问题:

  1. I cannot create a functional Save method to write to file, I have tried several methods in System.IO 我无法创建功能性的Save方法写入文件,我在System.IO尝试了几种方法
  2. When I changed the list to a one-dimensional array, it would constantly overwrite it, I want to simulate MySQL to familiarize myself for later on. 当我将列表更改为一维数组时,它将不断覆盖它,我想模拟MySQL以使自己熟悉以备后用。

The Button Click event that calls the Constructor: 调用构造方法的Button Click事件:

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);
        }
    }

According to your comment, it sounds like you want to append and not write . 根据您的评论,听起来您想追加而不是撰写 If you want to append to a file (ie add to whats already there) you need to use the AppendAllLines() function. 如果要追加到文件(即添加到已有文件),则需要使用AppendAllLines()函数。

However you have bigger issues because you are trying to write a List of objects, not strings to your file. 但是,您遇到的问题更大,因为您正在尝试将对象列表而不是字符串写入文件。 If you want to just write the passwords, you need this: 如果您只想编写密码,则需要这样做:

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

This method will append to a file if it exists, if it does not exist it just creates a new file. 如果存在,此方法将追加到文件中;如果不存在,则仅创建一个新文件。

Documentation here 这里的文件

WriteAllLines expects an string[] as the second parameter. WriteAllLines期望将string[]作为第二个参数。 So you need to create a way to represent a single Account object as a string. 因此,您需要创建一种将单个Account对象表示为字符串的方法。 The easiest way is to override the ToString method. 最简单的方法是覆盖ToString方法。 Then use the Linq Select method to select them. 然后使用Linq Select方法选择它们。

Also, it would be better if the Account class did not also contain the list of accounts. 另外,如果Account类不包含帐户列表,则更好。 That should really be a separate class. 那真的应该是一个单独的类。 Try something like this: 尝试这样的事情:

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}";
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM