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

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

新規登録して質問してみよう
ただいま回答率
85.49%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

1回答

4853閲覧

Visual Studio 2017でC#の開発をしています。約18万件のdatファイル(合計約9ギガ)を読み込み必要なデータを抽出しリストとしてまとめたCSVを1つ作成するようにしています。

ShinyaKojima

総合スコア18

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

1クリップ

投稿2019/04/05 00:37

お世話になっております。
Visual Studio2017でC#の開発をしています。
内容としては比較的単純な動作(datファイルの中から必要なキーとなる行のみを抽出しそれぞれの値を格納、csvファイルとして書き出す作業をフォルダ内のdatファイルの数だけ作業を繰り返すようにしています。
実行時に検証としてデータを約1万6千件程度で試したところ、正しく動作しcsvファイルも想定していた内容で作成されました。
しかし、4万件を超えたあたりから

「リソース制限を超過しています。このウィンドウのデータコレクションが停止しました。」
という表示が出て処理が途中で止まりcsvファイルが作成されませんでした。

1つのフォルダに約18万件のdatファイル(1つ約40kb程度)が入っているものをまとめて処理して1つのcsvにしたいと考えていますが、解決策が見つかりません。

詳しい方、どうかご教授をお願い致します。

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 string 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>(); // 読み込み foreach (string fileName in Directory.GetFiles(@"C:\検証用\検証データ\MLOG_RCV\BACKUP", "*.dat")) using (var sr = new StreamReader(fileName, 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(@"C:\検証用\検証データ\MLOG_RCV\BACKUP\list.csv")) using (var outputDat = new CsvHelper.CsvWriter(sw)) { outputDat.Configuration.HasHeaderRecord = false; outputDat.Configuration.RegisterClassMap<NewDatRowValuesMapper>(); outputDat.WriteRecords(writeDatList); } } } }

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

提示されている件数が入力総件数なのか入力ファイル1つあたりの件数なのか、出力件数なのか記載されていないので的外れかもしれませんが

1.1つのCSVを読み込む
2.1で読み込んだデータから必要データを抽出する
3.1~2をファイル数分繰り返す
4.抽出したデータを1つのCSVへと出力する
という流れですよね。

これを
1.1つのCSVを読み込む
2.1で読み込んだデータから必要データを抽出する
3.抽出したデータを1つのCSVへと追記出力する
4.1~3をファイル数分繰り返す
とすれば、使用する資源を減らすことができるのではないでしょうか。

また、CsvHelperを使用せずにテキストファイルとして1行づつ読み込み順次処理していくことやデータベースの使用を考えたほうがいいかもしれません。

追記

出力用のリストを使用しない場合のサンプル

C#

1 static void Main(string[] args) 2 { 3 // 書き出し用のファイルを用意 4 using (var sw = new StreamWriter(@"C:\検証用\検証データ\MLOG_RCV\BACKUP\list.csv")) 5 using (var outputDat = new CsvHelper.CsvWriter(sw)) 6 { 7 outputDat.Configuration.HasHeaderRecord = false; 8 outputDat.Configuration.RegisterClassMap<NewDatRowValuesMapper>(); 9 10 // 読み込み 11 foreach (string fileName in Directory.GetFiles(@"C:\検証用\検証データ\MLOG_RCV\BACKUP", "*.dat")) 12 using (var sr = new StreamReader(fileName, System.Text.Encoding.GetEncoding("shift_jis"))) 13 using (var inputDat = new CsvHelper.CsvReader(sr)) 14 { 15 inputDat.Configuration.HasHeaderRecord = false; 16                   ・ 17                   ・ 18                   ・ 19                   ・ 20 21 // 書き出し 22 outputDat.WriteRecord(newRow); 23 } 24

ただ、エラーの出る箇所(入力ファイルが大きい等)によっては、上記の変更でも改善しないでしょう。

投稿2019/04/05 01:04

編集2019/04/05 01:46
YAmaGNZ

総合スコア10242

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ShinyaKojima

2019/04/05 01:28

説明が不足していて申し訳ありません。 1.1つのCSVを読み込む 2.1で読み込んだデータから必要データを抽出する 3.1~2をファイル数分繰り返す 4.抽出したデータを1つのCSVへと出力する 流れで正しいです。 3.抽出したデータを1つのCSVへと追記出力する の部分がよく分からないのですが詳しく教えていただけますでしょうか? C#初心者でまだ知識が足りないようです。
ShinyaKojima

2019/04/05 02:15

詳しい説明ありがとうございました。 データ量が多く処理に時間がかかる為 まだ何とも言えませんが参考にさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問