附加到 csv 文件(csv 助手)在 csv 文件中提供重复条目

Appending to csv file (csv helper) gives duplicate entry in csv file

使用以下代码,我尝试将在控制台中输入的用户附加到现有的 csv 文件中。我正在使用 CSV 帮助程序并阅读了文档。

首先,我从 csv 文件加载用户并使用以下代码将它们存储在列表中:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Globalization;
using System.Linq;
using CsvHelper;

namespace GimpiesConsoleOOcsvListUI
{
    public class UserList
    {
        public static List<User> LoadUsersFromCSV()
        {
            // using (var mem = new MemoryStream())
            // using (var writer = new StreamWriter(mem))
            using (var reader = new StreamReader("users.csv"))
            using (var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture))
            {
                // csvReader.Configuration.Delimiter = ";";
                // csvReader.Configuration.IgnoreBlankLines = true;
                csvReader.Configuration.HasHeaderRecord = true;
                // csvReader.Configuration.PrepareHeaderForMatch = (string header, int index) => header.ToLower();
                // csvReader.Configuration.MissingFieldFound = null;
                csvReader.Read();
                csvReader.ReadHeader();
                    
                // Store all content inside a new List as objetcs
                var users = csvReader.GetRecords<User>().ToList();  
                    
                return users;
                // try
                // {
                    
                                  
                // }
                // catch (CsvHelper.HeaderValidationException exception)
                // {
                //     Console.WriteLine(exception);
                // }
                
            }
            
        }
    }
}

新用户通过此代码进入:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Globalization;
using System.Linq;
using CsvHelper;

namespace GimpiesConsoleOOcsvListUI
{
    public class RegisterManager
    {
        public void Register(List<User> users)
        {
            // Get user input
            Console.WriteLine("Enter username:");
            string username = Console.ReadLine();

            Console.WriteLine("Enter email:");
            string email = Console.ReadLine();

            Console.WriteLine("Enter password:");
            string password = Console.ReadLine();

            Console.WriteLine("Enter userrole (typ admin, purchase or sales):");
            string userrole = Console.ReadLine();

            // Create fresh instance to save input in memory
            User user = new User(username, email, password, userrole);

            // Adds the user to the excisting list
            users.Add(user);

            FileOperations fo = new FileOperations();
            // Calling the method from FileOperations.cs to write the List here to a CSV file
            fo.WriteUsersToCSV(users);
        }
    }
}

然后使用名为 WriteUsersToCSV 的方法将输入的用户写入现有的 csv 文件:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Globalization;
using System.Linq;
using CsvHelper;

namespace GimpiesConsoleOOcsvListUI
{
    // Handles CRUD within CSV files and able to save them
    public class FileOperations
    {
        // Appends to CSV file from List
        public void WriteUsersToCSV(List<User> users)
        {
            // Append to the file
            using (var stream = File.Open("users.csv", FileMode.Append))
            using (var writer = new StreamWriter(stream))
            using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                csvWriter.Configuration.HasHeaderRecord = false;
                csvWriter.WriteRecords(users);
                
                Console.WriteLine("New user added to users.csv");
            }
        }

        // Writes to CSV file from List
        public void WriteUsersToNewCSVFile(List<User> users)
        {
            using (var writer = new StreamWriter("users.csv"))
            using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                // csvWriter.Configuration.Delimiter = ";";
                csvWriter.Configuration.HasHeaderRecord = true;
                csvWriter.Configuration.AutoMap<User>();
                csvWriter.WriteHeader<User>();
                csvWriter.WriteRecords(users);
                
                Console.WriteLine("New file users.csv created!");
            }
        }

        // Reads from CSV file and displays content from it 
        public void ReadUsersFromCSV()
        {
            using (var reader = new StreamReader("users.csv"))
            using (var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture))
            {
                try
                {
                    // csvReader.Configuration.Delimiter = ";";
                    // csvReader.Configuration.IgnoreBlankLines = true;
                    csvReader.Configuration.HasHeaderRecord = true;
                    // csvReader.Configuration.PrepareHeaderForMatch = (string header, int index) => header.ToLower();
                    // csvReader.Configuration.MissingFieldFound = null;
                    csvReader.Read();
                    csvReader.ReadHeader();
                    
                    // Store all content inside a new List as objetcs
                    var records = csvReader.GetRecords<User>().ToList();
                    
                    // Loop through the List and show them in Console (connect to values in the constructor User.cs record.username etc..)
                    foreach (var record in records)
                    {
                        Console.WriteLine($"{record.username } | {record.email} | {record.password} | {record.userrole}");
                    }
                }
                catch (CsvHelper.HeaderValidationException exception)
                {
                    Console.WriteLine(exception);
                }
            }
        }

        // Writes to CSV file from List
        public void SaveGimpiesToCSV(List<Gimpies> gimpies)
        {
            // using (var mem = new MemoryStream())
            // using (var writer = new StreamWriter(mem))
            using (var writer = new StreamWriter("gimpies.csv"))
            using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                csvWriter.Configuration.Delimiter = ";";
                csvWriter.Configuration.HasHeaderRecord = true;
                csvWriter.Configuration.AutoMap<Gimpies>();
                csvWriter.WriteHeader<Gimpies>();
                csvWriter.WriteRecords(gimpies);
                writer.Flush();
                // var result = Encoding.UTF8.GetString(mem.ToArray());
                // Console.WriteLine(result);
            }
        }
            
        
    }
    
}

但是当我写入现有的 csv 文件时,我再次获得了前三个用户!查看结果:

username,email,password,userrole,
Inkoop,inkoop@gimpies.nl,123,purchase
Verkoop,verkoop@gimpies.nl,123,sales
Beheer,beheer@gimpies.nl,123,admin
Inkoop,inkoop@gimpies.nl,123,purchase
Verkoop,verkoop@gimpies.nl,123,sales
Beheer,beheer@gimpies.nl,123,admin
Bas,bas@bas.nl,123,admin

在这里你看到我添加了用户 Bas,但是又添加了 Inkoop 和 Verkoop 以及 Beheer。

我在代码中找不到需要删除或更改的内容。

确定这是我的 Program.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Globalization;
using System.Linq;
using CsvHelper;

namespace GimpiesConsoleOOcsvListUI
{
    class Program
    {
        static void Main(string[] args)
        {
            // List of default users
            // List<User> users = UserList.DefaultUsers();
            
            // Working on it... Try to read csv file first and try to read list from method in UserList.cs
            // UserList ul = new UserList();
            List<User> users = UserList.LoadUsersFromCSV();
            // List<User> users = 
            // ul.LoadUsersFromCSV(users);
        

            // Create login instance
            LoginManager loginMgr = new LoginManager();

            // Create stock instance
            Stock stock = new Stock();

            Start:
            // Welcome message
            Console.WriteLine("Welcome to the Gimpies Console Application! Choose 1 to login or 2 to exit this application:");

            // Get input from user
            string input = Console.ReadLine();

            // Set to false to check if login fails or not
            bool successfull = false;

            while (!successfull)
            {
                if(input == "1")
                {
                    Console.WriteLine("Enter your username:");
                    string username = Console.ReadLine();
                    Console.WriteLine("Enter your password:");
                    string password = Console.ReadLine();

                    foreach (User user in users)
                    {
                        if (username == user.username && password == user.password && user.userrole == "admin")
                            {
                                // Create Admin instance to be able to call methods in that class
                                Admin am = new Admin();
                                // Calling the method in Admin.cs to start Menu logic
                                am.AdminLoggedIn(users); 
                                
                                successfull = true;
                                break; 
                            }

                        if (username == user.username && password == user.password && user.userrole == "purchase")
                            {
                                // Create Purchase instance to be able to call methods in that class
                                Purchase pc = new Purchase();
                                // Calling the method in Purchase.cs to start Menu logic
                                pc.PurchaseLoggedIn(users);
                                
                                successfull = true;
                                break; 
                            }
                        
                        if (username == user.username && password == user.password && user.userrole == "sales")
                            {
                                // Create Sales instance to be able to call methods in that class
                                Sales sl = new Sales();
                                // Calling the method in Sales.cs to start Menu logic
                                sl.SalesLoggedIn(users);
                                
                                successfull = true;
                                break; 
                            }
                    }

                        if (!successfull)
                            {
                                Console.WriteLine("Your username or password is incorrect, try again !!!");
                            }
                }

                else if (input == "2")
                {          
                    Environment.Exit(-1);
                }

                else if (input == "3")
                {
                    FileOperations fo = new FileOperations();
                    // Calling the method from FileOperations.cs to write the List here to a CSV file
                    fo.WriteUsersToCSV(users);
                    goto Start;
                }

                else if (input == "4")
                {
                    FileOperations fo = new FileOperations();
                    // Calling the method from FileOperations.cs to write the List here to a CSV file
                    fo.ReadUsersFromCSV();
                    goto Start;
                }

                else
                {
                    Console.WriteLine("Try again !!!");
                    break;
                }
            }
            
            // // Loop over stored users within instances inside the list where users are added
            // foreach (User user in users)
            // {
            
            //     if(loginMgr.Login(user))
            //     {
            //         // Login successfull
            //         Console.WriteLine("Login user " + user.UserName);

            //     }
            //     else
            //     {
            //         // Not successfull

            //     }
            // }  
            
        }
    }
}

还有我的 GitLab 存储库:https://gitlab.com/marianydesign/gimpiesconsoleoocsvlist

我看到两个选项供您选择。确保您只实施两个选项之一。

选项 #1(您的代码试图实现的选项),您可以将新记录附加到文件数据。此选项将要求您跟踪文件中已有的内容,以便您可以排除写入文件中已有的记录。

选项#2,您可以每次用完整的用户列表覆盖文件。不附加每次只写完整的文件。

实施选项 #1:

此选项只需要更改您的 else if (input == "3") 条件。更新条件,以便它将要写入的列表与文件中已有的列表进行比较,并排除写入文件中已有的任何 Users...

else if (input == "3")
{
    FileOperations fo = new FileOperations(); 
    // get existing users from file
    List<User> userInFile = UserList.LoadUsersFromCSV(); 
    // remove existing users from update list to create final list for writing
    List<User> finalList = users.Where(u => !userInFile.Any(uf => uf.email.Equals(u.email, StringComparison.InvariantCultureIgnoreCase))).ToList();
    fo.WriteUsersToCSV(users);
    goto Start;
}

实施选项 #2:

此选项需要更改您的 WriteUsersToCSV 方法。

public void WriteUsersToCSV(List<User> users)
{
   // overwrite the file each time; indicated by the `false` parameter
   using (var writer = new StreamWriter("users.csv", false))
   using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture))
   {
      // csvWriter.Configuration.HasHeaderRecord = false; // commented out as we write the whole file every time including the header
      csvWriter.WriteRecords(users);
      Console.WriteLine("New user added to users.csv");
   }
}