プログラム 技術

C#でCSVファイルからDiffを取る

前回はPowerShellでCSVファイルに対するDiffを出力しましたが今回はC#でのDiffの出力の仕方となります

前回の記事
PowerShellでCSVファイルからDiffを取る - ナストンのまとめ
PowerShellでCSVファイルからDiffを取る - ナストンのまとめ

同じ列内容で構成されている2つのCSVファイルからDiff(差分)をプログラムで取る必要があったので、その時のメモとなり ...

前回の記事へ

名称バージョン
C#.Net 8.0

キーベースで比較

まずはPowerShellの時と同じように特定の列を指定してDiffを取る方法となります

var rows1 = ReadCSV(file1);
var rows2 = ReadCSV(file2);
var results = new List<DiffResult>();

Console.WriteLine($"ファイル1: {rows1.Count} 行");
Console.WriteLine($"ファイル2: {rows2.Count} 行");
Console.WriteLine($"キー列 '{keyColumn}' を使用して比較中...");

// ハッシュテーブルを作成
var hash1 = rows1.ToDictionary(r => r.GetValue(keyColumn), r => r);
var hash2 = rows2.ToDictionary(r => r.GetValue(keyColumn), r => r);

// ファイル1にのみ存在するレコード
foreach (var kvp in hash1)
{
    if (!hash2.ContainsKey(kvp.Key))
    {
        results.Add(new DiffResult
        {
            Row = kvp.Value,
            Type = DiffType.OnlyInFile1,
            SourceFile = file1,
            KeyValue = kvp.Key
        });
    }
}

// ファイル2にのみ存在するレコード
foreach (var kvp in hash2)
{
    if (!hash1.ContainsKey(kvp.Key))
    {
        results.Add(new DiffResult
        {
            Row = kvp.Value,
            Type = DiffType.OnlyInFile2,
            SourceFile = file2,
            KeyValue = kvp.Key
        });
    }
}

// 両方に存在するが内容が異なるレコード
foreach (var kvp in hash1)
{
    if (hash2.ContainsKey(kvp.Key))
    {
        var row1 = kvp.Value;
        var row2 = hash2[kvp.Key];
        
        if (!AreRowsEqual(row1, row2, keyColumn))
        {
            results.Add(new DiffResult
            {
                Row = row1,
                Type = DiffType.Modified_File1,
                SourceFile = file1,
                KeyValue = kvp.Key
            });
            
            results.Add(new DiffResult
            {
                Row = row2,
                Type = DiffType.Modified_File2,
                SourceFile = file2,
                KeyValue = kvp.Key
            });
        }
    }
}

return results;

以下のCSVファイルをそれぞれ用意して『Name』列をキーとして実行した場合

# CSV1
ID,Name,Age,Department
1,田中太郎,30,営業部
2,佐藤花子,25,開発部
3,鈴木次郎,35,人事部
4,高橋三郎,28,営業部

# CSV2
ID,Name,Age,Department
1,田中太郎,31,営業部
2,佐藤花子,25,開発部
3,鈴木次郎,35,総務部
5,山田五郎,29,開発部

# 実行結果
"ID","Name","Age","Department","DiffType","ComparedFile"
"4","高橋三郎","28","営業部","OnlyInFile1",".\sample1.csv"
"5","山田五郎","29","開発部","OnlyInFile2",".\sample2.csv"
"1","田中太郎","30","営業部","Modified_File1",".\sample1.csv"
"1","田中太郎","31","営業部","Modified_File2",".\sample2.csv"
"3","鈴木次郎","35","人事部","Modified_File1",".\sample1.csv"
"3","鈴木次郎","35","総務部","Modified_File2",".\sample2.csv"

PowerShellと同じように片方のCSVにしかないデータと両方にあるかつ、データの違いがあるものが出力されています

行番号ベースで比較

続いて行番号ベースで比較となります

var rows1 = ReadCSV(file1);
var rows2 = ReadCSV(file2);
var results = new List<DiffResult>();

Console.WriteLine($"ファイル1: {rows1.Count} 行");
Console.WriteLine($"ファイル2: {rows2.Count} 行");
Console.WriteLine("行番号ベースで比較中...");

int maxRows = Math.Max(rows1.Count, rows2.Count);

for (int i = 0; i < maxRows; i++)
{
    var row1 = i < rows1.Count ? rows1[i] : null;
    var row2 = i < rows2.Count ? rows2[i] : null;
    
    if (row1 == null)
    {
        // ファイル2にのみ存在
        results.Add(new DiffResult
        {
            Row = row2,
            Type = DiffType.OnlyInFile2,
            SourceFile = file2,
            KeyValue = (i + 1).ToString()
        });
    }
    else if (row2 == null)
    {
        // ファイル1にのみ存在
        results.Add(new DiffResult
        {
            Row = row1,
            Type = DiffType.OnlyInFile1,
            SourceFile = file1,
            KeyValue = (i + 1).ToString()
        });
    }
    else
    {
        // 両方に存在、内容を比較
        if (!AreRowsEqual(row1, row2))
        {
            results.Add(new DiffResult
            {
                Row = row1,
                Type = DiffType.Modified_File1,
                SourceFile = file1,
                KeyValue = (i + 1).ToString()
            });
            
            results.Add(new DiffResult
            {
                Row = row2,
                Type = DiffType.Modified_File2,
                SourceFile = file2,
                KeyValue = (i + 1).ToString()
            });
        }
    }
}

return results;

以下のCSVファイルをそれぞれ用意して実行した場合

# CSV1
ID,Name,Age,Department
1,田中太郎,30,営業部
2,佐藤花子,25,開発部
3,鈴木次郎,35,人事部
4,高橋三郎,28,営業部

# CSV2
ID,Name,Age,Department
1,田中太郎,31,営業部
2,佐藤花子,25,開発部
3,鈴木次郎,35,総務部
5,山田五郎,29,開発部

# 実行結果
"ID","Name","Age","Department","RowNumber","DiffType","ComparedFile"
"1","田中太郎","30","営業部","1","Modified_File1",".\sample1.csv"
"1","田中太郎","31","営業部","1","Modified_File2",".\sample2.csv"
"3","鈴木次郎","35","人事部","3","Modified_File1",".\sample1.csv"
"3","鈴木次郎","35","総務部","3","Modified_File2",".\sample2.csv"
"4","高橋三郎","28","営業部","4","Modified_File1",".\sample1.csv"
"5","山田五郎","29","開発部","4","Modified_File2",".\sample2.csv"

こちらもPowerShellの時と同じように片方のCSVにしかないデータと両方にあるかつ、データの違いがあるものが出力されています

最後に

これでC#でもCSVのDiffを出力することができます。次回はC#での実装について書こうと思います
また、今回紹介したコードはいつものごとくGitHubにアップしていますので参考にしてみてください

サンプルコード
BlogSampleCodeProjects/CSVDiff_CSharp at main · nasuton/BlogSampleCodeProjects · GitHub
BlogSampleCodeProjects/CSVDiff_CSharp at main · nasuton/BlogSampleCodeProjects · GitHub

Project for sample code used in the blog.(Blogで記載しているサンプルコード ...

GitHubへ

会社紹介

私が所属しているアドバンスド・ソリューション株式会社(以下、ADS)は一緒に働く仲間を募集しています

会社概要
「技術」×「知恵」=顧客課題の解決・新しい価値の創造

この方程式の実現はADSが大切にしている考えで、技術を磨き続けるgeekさと、顧客を思うloveがあってこそ実現できる世界観だと思っています
この『love & geek』の精神さえあれば、得意不得意はno problem!
技術はピカイチだけど顧客折衝はちょっと苦手。OKです。技術はまだ未熟だけど顧客と知恵を出し合って要件定義するのは大好き。OKです
凸凹な社員の集まり、色んなカラーや柄の個性が集まっているからこそ、常に新しいソリューションが生まれています

ミッション
私たちは、テクノロジーを活用し、業務や事業の生産性向上と企業進化を支援します

ホームページ
アドバンスド・ソリューション株式会社|ADS Co., Ltd.
アドバンスド・ソリューション株式会社|ADS Co., Ltd.

Microsoft 365/SharePoint/Power Platform/Azure による DX コンサル・シス ...

サイトへ移動

PR

-プログラム, 技術
-