如何使用 CsvHelper 包将 C# 列表写入 CSV
How to write a C# List to CSV with CsvHelper package
我有一个简单的控制台应用程序,其中包含 Program.cs 中 3 个用户的列表。在 Program.cs 中我想调用 FileOperations.cs
中的方法。
首先是我的 Program.cs
:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CsvHelper;
namespace GimpiesConsoleOOcsvListUI
{
class Program
{
static void Main(string[] args)
{
// Create user default instances
User user0 = new User("Beheer", "beheer@gimpies.nl", "123");
User user1 = new User("Inkoop", "inkoop@gimpies.nl", "123");
User user2 = new User("Verkoop", "verkoop@gimpies.nl", "123");
// List of users (with a list you can add, get and remove items in the list)
List<User> users = new List<User>();
users.Add(user0);
users.Add(user1);
users.Add(user2);
// Create login instance
LoginManager loginMgr = new LoginManager();
Start:
// Welcome message
Console.WriteLine("Welcome to GimpiesTerminal! Choose 1 to login or 2 to register:");
// Get input from user
string input = Console.ReadLine();
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)
{
Console.WriteLine("You have successfully logged in !!!");
Console.ReadLine();
successfull = true;
break;
}
}
if (!successfull)
{
Console.WriteLine("Your username or password is incorrect, try again !!!");
}
}
else if (input == "2")
{
// Get user input
Console.WriteLine("Enter your username:");
string username = Console.ReadLine();
Console.WriteLine("Enter your email:");
string email = Console.ReadLine();
Console.WriteLine("Enter your password:");
string password = Console.ReadLine();
// Create fresh instance to save input in memory
User user = new User(username, email, password);
// Adds the user to the excisting list
users.Add(user);
successfull = true;
goto Start;
}
else if (input == "3")
{
// Here I want to call the method from FileOperations.cs to write the List here to a CSV file.
}
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
// }
// }
}
}
}
这是我的 FileOperations.cs
:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CsvHelper;
namespace GimpiesConsoleOOcsvListUI
{
public class FileOperations
{
// Handles CRUD within CSV files and able to save them
public void SaveToCSV(User user)
{
using (var mem = new MemoryStream())
using (var writer = new StreamWriter(mem))
using (var csvWriter = new CsvWriter(writer))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecords(user);
writer.Flush();
var result = Encoding.UTF8.GetString(mem.ToArray());
Console.WriteLine(result);
}
}
}
}
我在 FileOperations.cs
的第 16 行收到以下错误:
StreamWriter 编写器
参数 1:无法从 System.IO.StreamWriter
转换为 CsvHelper.ISerializer
第 23 行:
用户用户
参数 1:无法从 GimpiesConsoleOOcsvListUI.User
转换为 System.Collections.IEnumerable
我是 C# 的新手,所以我希望你不介意这是一个简单的解决问题! :-)
您收到错误是因为您在这两种情况下都传递了错误的参数类型。
CsvWriter
没有只接受一个参数为 TextWriter
的构造函数。我对这个库不是很熟悉,但我相信它过去可能做过。我怀疑您从互联网上以前的示例中复制了您的代码,这些示例已经过时了。
解决这个问题的简单方法是再添加两个参数:
using (var csvWriter = new CsvWriter(writer, CultureInfo.CurrentCulture, false))
第二个错误是因为 CsvWriter.WriteRecords
需要一个 IEnumerable
参数,而不是单个实例。要解决此问题,您需要将 List<User>
传递给它,因此整个代码变为:
public void SaveToCSV(List<User> users)
{
using (var mem = new MemoryStream())
using (var writer = new StreamWriter(mem))
using (var csvWriter = new CsvWriter(writer, CultureInfo.CurrentCulture, false))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecords(users);
writer.Flush();
var result = Encoding.UTF8.GetString(mem.ToArray());
Console.WriteLine(result);
}
}
如果您想序列化单个用户 object 并显示其序列化后的 header 和值,您可以尝试以下代码:
public void SaveToCSV(User user)
{
using (var writer = new StringWriter())
using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture, leaveOpen: true))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecord(user);
csvWriter.Flush();
var result = writer.ToString();
Console.WriteLine(result);
}
}
它正在使用图书馆 CsvWriter
所需的简单 StringWriter
实例,并使用 InvariantCulture
信息进行内容序列化。在这种情况下,第三个参数 leaveOpen
必须设置为 true
,因为您对 using
块范围内的 StringWriter
的内容感兴趣。最后但同样重要的是,您当前正在传递 User
的单个实例,因此您必须调用 WriteRecord
方法而不是 WriteRecords
.
如果你想把它写到实际文件中,你必须做一些不同的事情:
public void SaveToCSV(User user)
{
using (var writer = new StreamWriter("path\to\your\file.csv"))
using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecord(user);
}
}
您不需要在第二个示例中调用 Flush
,因为 using
块的末尾会为您调用它,而您对其范围内的 CSV 内容不感兴趣。
我有一个简单的控制台应用程序,其中包含 Program.cs 中 3 个用户的列表。在 Program.cs 中我想调用 FileOperations.cs
中的方法。
首先是我的 Program.cs
:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CsvHelper;
namespace GimpiesConsoleOOcsvListUI
{
class Program
{
static void Main(string[] args)
{
// Create user default instances
User user0 = new User("Beheer", "beheer@gimpies.nl", "123");
User user1 = new User("Inkoop", "inkoop@gimpies.nl", "123");
User user2 = new User("Verkoop", "verkoop@gimpies.nl", "123");
// List of users (with a list you can add, get and remove items in the list)
List<User> users = new List<User>();
users.Add(user0);
users.Add(user1);
users.Add(user2);
// Create login instance
LoginManager loginMgr = new LoginManager();
Start:
// Welcome message
Console.WriteLine("Welcome to GimpiesTerminal! Choose 1 to login or 2 to register:");
// Get input from user
string input = Console.ReadLine();
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)
{
Console.WriteLine("You have successfully logged in !!!");
Console.ReadLine();
successfull = true;
break;
}
}
if (!successfull)
{
Console.WriteLine("Your username or password is incorrect, try again !!!");
}
}
else if (input == "2")
{
// Get user input
Console.WriteLine("Enter your username:");
string username = Console.ReadLine();
Console.WriteLine("Enter your email:");
string email = Console.ReadLine();
Console.WriteLine("Enter your password:");
string password = Console.ReadLine();
// Create fresh instance to save input in memory
User user = new User(username, email, password);
// Adds the user to the excisting list
users.Add(user);
successfull = true;
goto Start;
}
else if (input == "3")
{
// Here I want to call the method from FileOperations.cs to write the List here to a CSV file.
}
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
// }
// }
}
}
}
这是我的 FileOperations.cs
:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CsvHelper;
namespace GimpiesConsoleOOcsvListUI
{
public class FileOperations
{
// Handles CRUD within CSV files and able to save them
public void SaveToCSV(User user)
{
using (var mem = new MemoryStream())
using (var writer = new StreamWriter(mem))
using (var csvWriter = new CsvWriter(writer))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecords(user);
writer.Flush();
var result = Encoding.UTF8.GetString(mem.ToArray());
Console.WriteLine(result);
}
}
}
}
我在 FileOperations.cs
的第 16 行收到以下错误:
StreamWriter 编写器
参数 1:无法从 System.IO.StreamWriter
转换为 CsvHelper.ISerializer
第 23 行:
用户用户
参数 1:无法从 GimpiesConsoleOOcsvListUI.User
转换为 System.Collections.IEnumerable
我是 C# 的新手,所以我希望你不介意这是一个简单的解决问题! :-)
您收到错误是因为您在这两种情况下都传递了错误的参数类型。
CsvWriter
没有只接受一个参数为 TextWriter
的构造函数。我对这个库不是很熟悉,但我相信它过去可能做过。我怀疑您从互联网上以前的示例中复制了您的代码,这些示例已经过时了。
解决这个问题的简单方法是再添加两个参数:
using (var csvWriter = new CsvWriter(writer, CultureInfo.CurrentCulture, false))
第二个错误是因为 CsvWriter.WriteRecords
需要一个 IEnumerable
参数,而不是单个实例。要解决此问题,您需要将 List<User>
传递给它,因此整个代码变为:
public void SaveToCSV(List<User> users)
{
using (var mem = new MemoryStream())
using (var writer = new StreamWriter(mem))
using (var csvWriter = new CsvWriter(writer, CultureInfo.CurrentCulture, false))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecords(users);
writer.Flush();
var result = Encoding.UTF8.GetString(mem.ToArray());
Console.WriteLine(result);
}
}
如果您想序列化单个用户 object 并显示其序列化后的 header 和值,您可以尝试以下代码:
public void SaveToCSV(User user)
{
using (var writer = new StringWriter())
using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture, leaveOpen: true))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecord(user);
csvWriter.Flush();
var result = writer.ToString();
Console.WriteLine(result);
}
}
它正在使用图书馆 CsvWriter
所需的简单 StringWriter
实例,并使用 InvariantCulture
信息进行内容序列化。在这种情况下,第三个参数 leaveOpen
必须设置为 true
,因为您对 using
块范围内的 StringWriter
的内容感兴趣。最后但同样重要的是,您当前正在传递 User
的单个实例,因此您必须调用 WriteRecord
方法而不是 WriteRecords
.
如果你想把它写到实际文件中,你必须做一些不同的事情:
public void SaveToCSV(User user)
{
using (var writer = new StreamWriter("path\to\your\file.csv"))
using (var csvWriter = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = true;
csvWriter.Configuration.AutoMap<User>();
csvWriter.WriteHeader<User>();
csvWriter.WriteRecord(user);
}
}
您不需要在第二个示例中调用 Flush
,因为 using
块的末尾会为您调用它,而您对其范围内的 CSV 内容不感兴趣。