c# .net
csharp .net CsvHelper
kimbs0301
2024. 10. 12. 17:09
c# .net csv 파일 쓰기 및 읽기
.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="33.0.1" />
</ItemGroup>
</Project>
Program.cs
using CsvHelper;
using CsvHelper.Configuration;
using CsvHelper.TypeConversion;
using System.Globalization;
using System.Text;
public class Program
{
static void Main(string[] args)
{
Write();
WriteAppend();
Console.WriteLine();
Read();
Console.WriteLine();
Read2();
Console.WriteLine();
Read3();
}
static void Write()
{
System.IO.File.Delete("C:/files/Item1.csv");
DateTime dateTime = DateTime.UtcNow;
List<Item> list = new();
list.Add(new Item() { ID = 1, Name = "a123~!@#$%^&*()_+", Description = "a", ItemType = EItemType.MONEY, EventStart = dateTime, EventEnd = dateTime, AttrGID = 1 });
list.Add(new Item() { ID = 2, Name = "한글", Description = "b", ItemType = EItemType.ARMOR, EventStart = dateTime, EventEnd = dateTime, AttrGID = 1 });
list.Add(new Item() { ID = 3, Name = "한\"글", Description = "c", ItemType = EItemType.ARMOR, EventStart = dateTime, EventEnd = dateTime, AttrGID = 1 });
list.Add(new Item() { ID = 4, Name = "'a3", Description = "d", ItemType = EItemType.ARMOR, EventStart = dateTime, EventEnd = dateTime, AttrGID = 1 });
var csvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Encoding = new UTF8Encoding(true), // UTF8-BOM: true
NewLine = "\n",
//Delimiter = ",",
//Mode = CsvMode.NoEscape, // "한""글" -> 한"글
TrimOptions = TrimOptions.InsideQuotes,
};
using (var streamReader = new StreamWriter("C:\\files\\Item1.csv", false, new UTF8Encoding(true)))
using (var csvWriter = new CsvWriter(streamReader, csvConfiguration, leaveOpen: true))
{
//var options = new TypeConverterOptions { Formats = new[] { "yyyy-MM-dd'T'HH:mm:ss.fff" } };
//csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);
//csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(options);
csvWriter.WriteRecords(list);
}
}
static void WriteAppend()
{
DateTime dateTime = DateTime.UtcNow;
List<Item> list = new();
list.Add(new Item() { ID = 5, Name = "123", Description = "d", ItemType = EItemType.ETC, EventStart = null, EventEnd = dateTime, AttrGID = 5 });
var csvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Encoding = new UTF8Encoding(true), // UTF8-BOM: true
NewLine = "\n",
HasHeaderRecord = false, // CSV Header 쓰지 않도록 설정
};
// 기존 csv 파일 하단에 추가하여 쓰기
using (var streamWriter = new StreamWriter("C:\\files\\Item1.csv", true, new UTF8Encoding(true)))
using (var csvWriter = new CsvWriter(streamWriter, csvConfiguration, leaveOpen: true))
{
csvWriter.WriteRecords(list);
}
}
static void Read()
{
var csvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Encoding = new UTF8Encoding(true), // UTF8-BOM: true
NewLine = "\n",
BadDataFound = null, // Unhandled exception. CsvHelper.BadDataException: You can ignore bad data by setting BadDataFound to null.
};
using (var streamReader = new StreamReader("C:\\files\\Item1.csv", new UTF8Encoding(true)))
using (var csvReader = new CsvReader(streamReader, csvConfiguration))
{
List<Item> list = csvReader.GetRecords<Item>().ToList();
foreach (var item in list)
{
Console.WriteLine($"{item.ID} {item.Name} {item.Description} {item.ItemType} {item.EventStart} {item.EventEnd} {item.AttrGID}");
}
}
}
static void Read2()
{
var csvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Encoding = new UTF8Encoding(true), // UTF8-BOM: true
NewLine = "\n",
Delimiter = ",",
//Mode = CsvMode.NoEscape, // 한"글 -> "한""글"
//TrimOptions = TrimOptions.InsideQuotes,
PrepareHeaderForMatch = options => options.Header.Trim('"'),
//BadDataFound = null, // Unhandled exception. CsvHelper.BadDataException: You can ignore bad data by setting BadDataFound to null.
};
using (var streamReader = new StreamReader("C:\\files\\Item2.csv", new UTF8Encoding(true)))
using (var csvReader = new CsvReader(streamReader, csvConfiguration))
{
csvReader.Context.TypeConverterCache.AddConverter<string>(new RemoveQuotesStringConverter());
csvReader.Context.TypeConverterCache.AddConverter<int>(new RemoveQuotesIntegerConverter());
List<Item> list = csvReader.GetRecords<Item>().ToList();
foreach (var item in list)
{
Console.WriteLine($"{item.ID} {item.Name} {item.Description} {item.ItemType} {item.EventStart} {item.EventEnd} {item.AttrGID}");
}
}
}
static void Read3()
{
var csvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Encoding = new UTF8Encoding(true), // UTF8-BOM: true
NewLine = "\n",
Delimiter = ",",
//Mode = CsvMode.NoEscape, // 한"글 -> "한""글"
//TrimOptions = TrimOptions.InsideQuotes,
PrepareHeaderForMatch = options => options.Header.Trim('"'),
//BadDataFound = null, // Unhandled exception. CsvHelper.BadDataException: You can ignore bad data by setting BadDataFound to null.
};
using (var streamReader = new StreamReader("C:\\files\\Content1.csv", new UTF8Encoding(true)))
using (var csvReader = new CsvReader(streamReader, csvConfiguration))
{
var options = new TypeConverterOptions { Formats = new[] { "yyyy-MM-dd'T'HH:mm:ss.fff", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm" } };
csvReader.Context.TypeConverterOptionsCache.RemoveOptions<DateTime>();
csvReader.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);
//csvReader.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(options);
csvReader.Context.TypeConverterCache.AddConverter<string>(new RemoveQuotesStringConverter());
csvReader.Context.TypeConverterCache.AddConverter<int>(new RemoveQuotesIntegerConverter());
csvReader.Context.TypeConverterCache.RemoveConverter<DateTime>();
csvReader.Context.TypeConverterCache.AddConverter<DateTime>(new RemoveEmptyDateTimeConverter());
List<Content> list = csvReader.GetRecords<Content>().ToList();
foreach (var item in list)
{
Console.WriteLine($"{item.ID} {item.Name} {item.Description} {item.ItemType} {item.EventStart} {item.EventEnd} {item.AttrGID}");
}
}
}
}
Converter.cs
using CsvHelper.Configuration;
using CsvHelper;
using CsvHelper.TypeConversion;
public class RemoveQuotesStringConverter : StringConverter
{
public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
{
if (text == null)
text = string.Empty;
var trimmed = text.Trim('"');
return base.ConvertFromString(trimmed, row, memberMapData);
}
}
public class RemoveQuotesIntegerConverter : Int32Converter
{
public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
{
if (text == null)
text = string.Empty;
var trimmed = text.Trim('"');
return base.ConvertFromString(trimmed, row, memberMapData);
}
}
public class RemoveEmptyDateTimeConverter : DateTimeConverter
{
private readonly TimeZoneInfo LocalTimeZone = TimeZoneInfo.Local; // Unspecified -> Local
public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
{
if (string.IsNullOrEmpty(text))
return TimeZoneInfo.ConvertTimeToUtc(DateTime.MinValue, LocalTimeZone); // return base.ConvertFromString("0001-01-01T00:00:00.000", row, memberMapData);
var textDateTime = base.ConvertFromString(text, row, memberMapData);
if (textDateTime == null)
return TimeZoneInfo.ConvertTimeToUtc(DateTime.MinValue, LocalTimeZone);
return TimeZoneInfo.ConvertTimeToUtc((DateTime) textDateTime, LocalTimeZone);
}
}
Models.cs
using CsvHelper.Configuration.Attributes;
public class Item
{
[Name("ID")]
public long ID { get; set; }
[Name("Name")]
public string Name { get; set; } = string.Empty;
[Name("Description")]
public string Description { get; set; } = string.Empty;
[Name("ItemType")]
public EItemType ItemType { get; set; } = EItemType.NONE;
[Name("EventStart")]
[Format("yyyy-MM-dd'T'HH:mm:ss.fff")]
public DateTime? EventStart { get; set; } = null;
[Name("EventEnd")]
[Format("yyyy-MM-dd'T'HH:mm:ss.fff")]
public DateTime? EventEnd { get; set; } = null;
[Name("AttrGID")]
public int AttrGID { get; set; }
}
public enum EItemType
{
NONE,
MONEY,
ARMOR,
ETC
}
public class Content
{
public long ID { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public EItemType ItemType { get; set; } = EItemType.NONE;
public DateTime EventStart { get; set; }
public DateTime EventEnd { get; set; }
public int AttrGID { get; set; }
}
references
https://joshclose.github.io/CsvHelper/getting-started/
https://stackoverflow.com/questions/66360488/csv-helper-read-file-with-double-quotes-in-field-data
https://stackoverflow.com/questions/39564585/csvhelper-changing-how-dates-and-times-are-output