C#でCSVを扱うときに便利なCSVHelperの使い方


## CSVHelperとは
C#でCSVを取り扱う際にCSVにまつわるもろもろのメンドクサイところをいい感じでやってくれるライブラリです。

https://qiita.com/mima_ita/items/f6b68d23ec9727badf96#csvhelper%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E4%BE%8B

↑でも書かれていますが、CSVファイルはカンマで区切られたファイル、という簡単なイメージほど、取り扱いが簡単ではありません。
その辺の面倒なところを助けてくれるのがここで紹介するCSVHelperになります。

[CsvHelper公式](https://joshclose.github.io/CsvHelper/)　を見ればだいたいわかりますが、備忘のため、記事にします。

## インストール

```nuget
Install-Package CsvHelper
```

## サンプル

ユーザー定義クラスのリストをCSVファイルに書き込むサンプル。

```c#
using CsvHelper;
using CsvHelper.Configuration;
using System.IO;
using System.Collections.Generic;
using CsvHelper.Configuration.Attributes;

class Hoge
{
	[Name("ユーザーID")]
	public int Id { get; set;}
	
	[Name("名前")]
	public string Name { get; set; }
	
	[Name("バージョン表記")]
	[Constant("foo")]
	public string Version{get;set;}
	
	[Ignore]
	public string Ignored { get; set; }
}

class HogeMapper : CsvHelper.Configuration.ClassMap<Hoge>
{
    public HogeMapper()
    {
        AutoMap(CultureInfo.InvariantCulture);
    }
}
class Program{
	static void Main()
	{
		List<Hoge> list = new List<Hoge>();
        list.Add(new Hoge {Id = 1, Name = "John"});
        list.Add(new Hoge {Id = 2, Name = "Paul"});
        list.Add(new Hoge {Id = 3, Name = "George"});
        list.Add(new Hoge {Id = 4, Name = "Ringo"});

		var config = new CsvConfiguration(System.Globalization.CultureInfo.InvariantCulture);
		config.HasHeaderRecord = true;
		config.ShouldQuote = (context) => true;

		using (StreamWriter sw = new StreamWriter(@"sample.csv", false, Encoding.GetEncoding("Shift_JIS")))
		using (var writer = new CsvWriter(sw, config))
		{
		    writer.Context.RegisterClassMap<HogeMapper>();
		    writer.WriteRecords(list);
		}

	}
}
```

出力結果  
>"ユーザーID","名前","バージョン表記"
>"1","John","foo"
>"2","Paul","foo"
>"3","George","foo"
>"4","Ringo","foo"

## 解説

```c#
var config = new CsvConfiguration(System.Globalization.CultureInfo.InvariantCulture);
config.HasHeaderRecord = true;
config.ShouldQuote = (context) => true;
```
上記のコードでは、CSVファイルをCsvWriter(後述)が解釈する際の条件(ヘッダ有無とか)を設定しています。

`config.HasHeaderRecord = true;`は先頭行にヘッダーがある、という定義、`config.ShouldQuote = (context) => true;`は各項目がダブルクォーテーションで囲まれている、という定義です。この設定が無いとデフォルトではダブルクォーテーションが勝手についたりつかなかったりします。

古い記事だとCsvWriterのコンストラクタにCsvConfigurationのパラメータが無く、インスタンス後にCsvWriterのConfigurationプロパティを経由して設定を変更しているものもありますが、現バージョン(27.0.0.0)ではConfigurationはreadonlyに変更になっておりプロパティの設定ができなくなっているので、CsvWriterを生成する前にCsvConfigurationを生成、設定を行います。

```c#
using (StreamWriter sw = new StreamWriter(@"sample.csv", false, Encoding.GetEncoding("Shift_JIS")))
using (var writer = new CsvWriter(sw, config))
{
    writer.Context.RegisterClassMap<HogeMapper>();
	writer.WriteRecords(list);
}
```
上記のコードでCSV出力をしています。
`new CsvWriter(sw, config)`で出力先のストリームとConfigurationをパラメータとしてCsvWriterを生成します。

`writer.Context.RegisterClassMap<HogeMapper>();`でユーザー定義クラスとCSVのマッピング方法を指示しています。

`writer.WriteRecords(list);`でList<Hoge>の各アイテムを一括でCSVファイルに出力しています。

### マッピングについて
CSVファイルとクラスのマッピングは自動で行われるようですが、ヘッダ項目を独自に設定したい場合などはクラスのAttributeで設定できます。
```c#
class Hoge
{
	[Name("ユーザーID")]
	public int Id { get; set;}
	
```
の`[Name("ユーザーID")]`がそれにあたります。

## 注意点
ネット上にすでに多くの記事がありますが、バージョンアップでかなり~~破壊的~~変更があるらしく、古い記事だと、記事のとおりに書いてもうまくいかないことが多々あります。  
(Configurationまわりとか)
なので、この記事も時間がたつと使えなくなるかもしれません・・・