13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CsvHelperの使い方が変わっていた( ゚Д゚)

Posted at

はじめに

以前開発した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の使い方がかなり変わっていて、びっくりしました。

13
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?