質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.81%

C# フォルダ内の複数のdatファイル内から必要なキーを抽出し1つのCSVファイルにリストとして書き出す

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,551

ShinyaKojima

score 18

前提・実現したいこと

初めて質問致します。至らない点があれば申し訳ございません。

最近C#を勉強し始めた初心者です。
表題の通り、あるフォルダ内にある複数のdatファイルの中から必要なキーを抽出してそれをまとめたCSVファイルを作成したいと考えています。
別の所で質問をして[Nugetパッケージの管理]から CsvHelper をインストール。

複数ファイルを読み込んで書き出し用リストに突っ込めば出来る
という風に教えていただいたのですが。
使い方を自分なりに調べてみましたがなかなか理解できず使いこなせていない状態です。
絶対パスで@"C:\検証用\検証データ\MLOG_RCVの中にワイルドカードでdatファイルを全て読み込もうとして@"C:\検証用\検証データ\MLOG_RCV\*.datのようにしたのですがハンドルされていない例外というエラーが発生しました。自分なりに調べて*が無効な文字ということは分かったのですが、この場合全てのファイルを読み込むためにはどのように書いたら良いのか分かりません。
下記のソースコードも殆ど理解できていないままなので間違いだらけかもしれません。

datファイルの中身は以下のようになっておりフォルダ内に数万件あります。
datファイル(カンマ区切りの4~5列、約800行程度)
ProcessData,LOT_ID,3,AP0076686.00C,
ProcessData,LOT_ID_SUB,3,AP0076686.00,
ProcessData,LOT_NO,3,AP0076686,
ProcessData,WAFER_ID,3,AP0076686.19,
ProcessData,WAFER_NO,1,19,
ProcessData,PRODSPEC_ID,3,T5DH20001-00001.00,
ProcessData,PRODGRP_ID,3,T5DH2,
ProcessData,PRODGRP_BIND,3,T5DH2,
ProcessData,MAIN_MAINPD_ID,3,A6L511NY.00,
ProcessData,MAINPD_ID,3,A6L511NY.00,
ProcessData,FLOW_TYPE,3,Main,
ProcessData,FLOW_TYPE_NO,1,1,
ProcessData,D_SEQNO,1,169,
ProcessData,OP_NO,3,PNH PEP.MA1,
ProcessData,OP_NO_NAME,3,本処理,
ProcessData,PD_IDENT,3,PPNHIMA1.00,
ProcessData,PD_IDENT_NAME,3,PEP,
ProcessData,EQP_GROUP_CODE,3,PKRF,
ProcessData,EQP_GROUP_NAME,3,KrF SCANNER(SK3000 + ES5),
ProcessData,EQP_GROUP_BIND,3,PKRF,
ProcessData,EQP_ID,3,PKRF004,
ProcessData,PH_RECIPE_ID,3,PES5MIX,
ProcessData,RCP_NAME_SPACE,3,PEPMA,
ProcessData,LC_RECIPE_ID,3,PKRF.01,
ProcessData,RECIPE_ID,3,PEPMA.PES5MIX,
ProcessData,S_DATE,4,2019/01/24 12:47:09,
ProcessData,E_DATE,4,2019/01/24 12:47:51,
ProcessData,CAST_ID,3,PA0-00349,
ProcessData,SLOT_NO,1,19,

この中から
EQP_IDの時PKRF004
LOT_IDの時AP0076686.00C
Wafer_IDの時AP0076686.19
S_DATEの時2019/01/24 12:47:09
のようにデータを取得し
PKRF004 AP0076686.00C AP0076686.19 2019/01/24 12:47:09
の並びで何100行のようにリスト化されたcsvファイルを作るのが最終的な目標です。
イメージとしては
1.1ファイルの読み込み、解析、必要情報の保持。
2.ファイルの書き出し。
3.ファイルの読み込み、解析、必要情報の保持。
4.ファイルの書き出し。(追記)
というように繰り返し処理を行えばよいと思うのですが  
ロジックの書き方などを理解できていない状態です。

ソースコードの誤りの修正も含めC#に詳しい方、どうかご教授をお願い致します。

発生している問題・エラーメッセージ

エラーメッセージ
ハンドルされていない例外
System.ArgumentException:'パスに無効な文字が含まれています。'

該当のソースコード

C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ConsoleApp1
{
    class DatRowValues
    {
        public string ProcessData { get; set; }

        public string KeyValue { get; set; }

        public int IntValue { get; set; }

        public string StringValue { get; set; }
    }

    class NewDatRowValues
    {
        public string EqpId { get; set; }

        public string LotId { get; set; }

        public string WaferId { get; set; }

        public DateTime SDate { get; set; }
    }

    class NewDatRowValuesMapper : CsvHelper.Configuration.ClassMap<NewDatRowValues>
    {
        public NewDatRowValuesMapper()
        {
            Map(x => x.EqpId).Index(0);
            Map(x => x.LotId).Index(1);
            Map(x => x.WaferId).Index(2);
            Map(x => x.SDate).Index(3).TypeConverterOption.Format("yyyy/MM/dd HH:mm:ss");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // 書き出し用の入れ物を用意
            var writeDatList = new List<NewDatRowValues>();

            // 読み込み
            using (var sr = new StreamReader(@"C:\検証用\検証データ\MLOG_RCV\*.dat", System.Text.Encoding.GetEncoding("shift_jis")))
            using (var inputDat = new CsvHelper.CsvReader(sr))
            {
                inputDat.Configuration.HasHeaderRecord = false;

                // 必要なキーとなる行のみ抽出
                var dat = inputDat.GetRecords<DatRowValues>();
                var targetRows = dat.Where(r =>
                r.KeyValue == "EQP_ID" ||
                r.KeyValue == "LOT_ID" ||
                r.KeyValue == "WAFER_ID" ||
                r.KeyValue == "S_DATE");

                // それぞれの値を格納
                var newRow = new NewDatRowValues();
                foreach (var row in targetRows)
                {
                    if (row.KeyValue == "EQP_ID")
                    {
                        newRow.EqpId = row.StringValue;
                    }
                    if (row.KeyValue == "LOT_ID")
                    {
                        newRow.LotId = row.StringValue;
                    }
                    if (row.KeyValue == "WAFER_ID")
                    {
                        newRow.WaferId = row.StringValue;
                    }
                    if (row.KeyValue == "S_DATE")
                    {
                        newRow.SDate = DateTime.Parse(row.StringValue);
                    }
                }
                writeDatList.Add(newRow);
            }

            // 書き出し
            using (var sw = new StreamWriter("list.csv"))
            using (var outputDat = new CsvHelper.CsvWriter(sw))
            {
                outputDat.Configuration.HasHeaderRecord = false;
                outputDat.Configuration.RegisterClassMap<NewDatRowValuesMapper>();
                outputDat.WriteRecords(writeDatList);
            }
        }
    }
}

試したこと

*が無効な文字ということなので1つのファイル名で直接入力してみましたが
ハンドルされていない例外
CsvHelper.TypeConversion.TypeConverterException: 'The conversion cannot be performed.
Text: '91G208446-19'
MemberType: System.Int32
TypeConverter: 'CsvHelper.TypeConversion.Int32Converter''
というメッセージが表示されました。

補足情報(FW/ツールのバージョンなど)

開発環境Visual Studio2017

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

using (var sr = new StreamReader(@"C:\検証用\検証データ\MLOG_RCV\*.dat", System.Text.Encoding.GetEncoding("shift_jis")))

これは、C:\検証用\検証データ\MLOG_RCV\*.dat という名前のファイルを読み取ろうとしています。
しかし * はファイル名として使用できない文字なので、System.ArgumentException:'パスに無効な文字が含まれています。' が発生しています。


foreach (string fileName in Directory.GetFiles(@"C:\検証用\検証データ\MLOG_RCV", "*.dat"))
using (var sr = new StreamReader(fileName, System.Text.Encoding.GetEncoding("shift_jis")))

このように変えてみてはどうでしょうか。
System.IO.Directory.GetFiles で特定のフォルダに含まれるdatファイルの一覧を取得し、foreach でループ処理しています。
Directory.GetFiles Method (System.IO) | Microsoft Docs


以下は余談です。

下記のソースコードも殆ど理解できていないままなので間違いだらけかもしれません。

理解しましょう。
理解しないまま書いたコードは、思わぬバグを引き起こしかねません。
何事も一足飛びにはいかないものですから、あせらずに一文ずつ丁寧に理解すると良いと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/04 10:11

    上記の通りに実行したら正しく動作致しました。
    御教授いただいた皆様大変ありがとうございました。

    キャンセル

  • 2019/04/04 10:20

    IntValueはstringでいいのですか?
    stringにすれば例外はでないでしょうが、データとしてその部分は数字のみが正しいのであれば、データが間違っていることになります。
    数字以外のデータも存在するのであればstringでいいでしょうが、最初そのように設計したのは、その部分が数字しかないからではないのですか?
    間違ったデータがあった場合、プログラムが例外で終了するのはダメですが、異常なデータでも処理するのは間違っています。
    try-catchなどで、例外が発生した場合はエラーが出たことをユーザーに通知すべきです。

    キャンセル

  • 2019/04/08 18:34

    返信遅くなり申し訳ありません。データとしてその部分を確認した際に数字以外にAやBやCなど文字列が含まれていることが分かりstringが正しいようです。最初の設計の際によく中身を確認しておらず早とちりしていました。今後気を付けます。 try-catchについても勉強してより良いコードを書けるように頑張ります。

    キャンセル

+3

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.81%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • トップ
  • C#に関する質問
  • C# フォルダ内の複数のdatファイル内から必要なキーを抽出し1つのCSVファイルにリストとして書き出す