はじめに
以前開発したWPFアプリではCsvHelperの19.0.0を利用していました。
そのとき使っていたコードは以下のような感じ。HasHeaderRecordやRegisterClassMapを使用しています。
処理の内容は、郵便番号辞書のCSVファイルからの読み込みです。
// CSV読み込み用のクラス
public class KenAllCSV
{
public string PostalCode { get; set; } //郵便番号
public string PrefectureKana { get; set; } //都道府県名カナ
public string MunicipalityKana { get; set; } //市区町村名カナ
public string TownAreaKana { get; set; } //町域名カナ
public string Prefecture { get; set; } //都道府県名
public string Municipality { get; set; } //市区町村名
public string TownArea { get; set; } //町域名
public int TownAreaContainAnyPostalCode { get; set; } //一町域が二以上の郵便番号で表される場合の表示
public int PostalCodeContainAnyTownArea { get; set; } //一つの郵便番号で二以上の町域を表す場合の表示
}
// CSV Mapperクラス
public class CsvMapperKenAll : CsvHelper.Configuration.ClassMap<KenAllCSV>
{
public CsvMapperKenAll()
{
Map(x => x.PostalCode).Name("郵便番号");
Map(x => x.PrefectureKana).Name("都道府県名カナ");
Map(x => x.MunicipalityKana).Name("市区町村名カナ");
Map(x => x.TownAreaKana).Name("町域名カナ");
Map(x => x.Prefecture).Name("都道府県名");
Map(x => x.Municipality).Name("市区町村名");
Map(x => x.TownArea).Name("町域名");
Map(x => x.TownAreaContainAnyPostalCode).Name("一町域が二以上の郵便番号で表される場合の表示");
Map(x => x.PostalCodeContainAnyTownArea).Name("一つの郵便番号で二以上の町域を表す場合の表示");
}
}
// CSV読み込み
private async Task ReadCsvAsync()
{
if (!string.IsNullOrWhiteSpace(ImportPath))
{
var tempDatas = new ObservableCollection<KenAllCSV>();
await Task.Run(() =>
{
CultureInfo cultureInfo = new CultureInfo("ja-JP");
using (var r = new StreamReader(ImportPath, Encoding.GetEncoding("SHIFT_JIS")))
using (var csv = new CsvHelper.CsvReader(r, cultureInfo))
{
// ヘッダー
csv.Configuration.HasHeaderRecord = true;
// マッピングルールを登録
csv.Configuration.RegisterClassMap<CsvMapperKenAll>();
// データを読み出し
var records = csv.GetRecords<KenAllCSV>();
// DataGridに出力
tempDatas = new ObservableCollection<KenAllCSV>();
foreach (var record in records)
{
tempDatas.Add(new KenAllCSV()
{
PostalCode = record.PostalCode,
PrefectureKana = Microsoft.VisualBasic.Strings.StrConv(record.PrefectureKana, VbStrConv.Wide),
MunicipalityKana = Microsoft.VisualBasic.Strings.StrConv(record.MunicipalityKana, VbStrConv.Wide),
TownAreaKana = Microsoft.VisualBasic.Strings.StrConv(record.TownAreaKana, VbStrConv.Wide),
Prefecture = record.Prefecture,
Municipality = record.Municipality,
TownArea = record.TownArea,
TownAreaContainAnyPostalCode = record.TownAreaContainAnyPostalCode,
PostalCodeContainAnyTownArea = record.PostalCodeContainAnyTownArea
});
}
}
});
AddressDatas = new ObservableCollection<KenAllCSV>(tempDatas);
}
}
CsvHelperを22.1.2にしたら、エラーが起きたので利用方法を変更しました
調べてみると、ヘッダーの読み込みやマッパーあたりが変わっていたようでした。
ググッて見ると、RegisterClassMapを使うのではなく、ClassMap使ったりといったものがありましたが、それでもエラーが起きたのでもう少し調べると、マッパーではなく、Attributesを使うようでした。
変更したらこんな感じでうまくいきました
CSV読み込み用のクラスにAttributesを使用する
using CsvHelper.Configuration.Attributes;
public class KenAllCSV
{
[Name("郵便番号")]
public string PostalCode { get; set; } //郵便番号
[Name("都道府県名カナ")]
public string PrefectureKana { get; set; } //都道府県名カナ
[Name("市区町村名カナ")]
public string MunicipalityKana { get; set; } //市区町村名カナ
[Name("町域名カナ")]
public string TownAreaKana { get; set; } //町域名カナ
[Name("都道府県名")]
public string Prefecture { get; set; } //都道府県名
[Name("市区町村名")]
public string Municipality { get; set; } //市区町村名
[Name("町域名")]
public string TownArea { get; set; } //町域名
[Name("一町域が二以上の郵便番号で表される場合の表示")]
public int TownAreaContainAnyPostalCode { get; set; } //一町域が二以上の郵便番号で表される場合の表示
[Name("一つの郵便番号で二以上の町域を表す場合の表示")]
public int PostalCodeContainAnyTownArea { get; set; } //一つの郵便番号で二以上の町域を表す場合の表示
}
CSV Mapperクラスは使用しません
CSV読み込み
CSV読み込みで、Configuration.HasHeaderRecordではなく、Read()で読み込みを行い、そのあとでReadHeader()でヘッダーの読み込みを行います。
private async Task ReadCsvAsync()
{
if (!string.IsNullOrWhiteSpace(ImportPath))
{
var tempDatas = new ObservableCollection<KenAllCSV>();
await Task.Run(() =>
{
CultureInfo cultureInfo = new CultureInfo("ja-JP");
using (var r = new StreamReader(ImportPath, Encoding.GetEncoding("SHIFT_JIS")))
using (var csv = new CsvHelper.CsvReader(r, cultureInfo))
{
// ヘッダーtrueはしない
// csv.Configuration.HasHeaderRecord = true;
//読み込み を先に行う
csv.Read();
// ヘッダー を次に行う
csv.ReadHeader();
// マッピングルールを登録 は使用しない
//csv.Configuration.RegisterClassMap<CsvMapperKenAll>();
// データを読み出し
var records = csv.GetRecords<KenAllCSV>();
// DataGridに出力
tempDatas = new ObservableCollection<KenAllCSV>();
foreach (var record in records)
{
tempDatas.Add(new KenAllCSV()
{
PostalCode = record.PostalCode,
PrefectureKana = Microsoft.VisualBasic.Strings.StrConv(record.PrefectureKana, VbStrConv.Wide),
MunicipalityKana = Microsoft.VisualBasic.Strings.StrConv(record.MunicipalityKana, VbStrConv.Wide),
TownAreaKana = Microsoft.VisualBasic.Strings.StrConv(record.TownAreaKana, VbStrConv.Wide),
Prefecture = record.Prefecture,
Municipality = record.Municipality,
TownArea = record.TownArea,
TownAreaContainAnyPostalCode = record.TownAreaContainAnyPostalCode,
PostalCodeContainAnyTownArea = record.PostalCodeContainAnyTownArea
});
}
}
});
AddressDatas = new ObservableCollection<KenAllCSV>(tempDatas);
}
}
以上でCsvHelperを利用できるようになりました。
しばらく、アップデートをしていないうちに、CsvHelperの使い方がかなり変わっていて、びっくりしました。