dポイントプレゼントキャンペーン実施中!

プログラムの勉強を始めたばかりのものです。
Visual Studio Community 2017 を使用して C# で Windows Form Application を勉強中です。

フォルダを指定してファイルサイズを合計してTextBoxに表示するツールを作成中です。
ただし、拡張子を除いたファイルパスが完全一致するものはサイズを合計したいです。

例えば以下のようなファイル群があったとします(※は補足内容です)。
C:\Users\バナナ.bmp ※ファイルサイズは100
C:\Users\バナナ.html ※ファイルサイズは90
C:\Users\バナナ.txt  ※ファイルサイズは70
C:\Users\みかん.html ※ファイルサイズは30
C:\Users\みかん.txt  ※ファイルサイズは120
C:\Users\りんご.bmp ※ファイルサイズは80

Button_ClickイベントでTextBoxに出力したいのが以下のような文字列です。
C:\Users\バナナ,260 ※3つのファイルサイズの合計
C:\Users\みかん,150 ※2つのファイルサイズの合計
C:\Users\りんご,80  ※単体のファイルサイズ

私の浅い知識で書いたのは以下のような感じです。

for (int i = 0; i < files.Length; i++)
{
  string fpass = Path.GetDirectoryName(files[i]);
  string fname = Path.GetFileNameWithoutExtension(files[i]);
  long filesize;

  // 最初のファイルの場合
  if (i == 0)
  {
    // ファイルサイズをチェック
    FileInfo fi = new FileInfo(files[i]);

    // ファイルパスをnewListFileに格納
    newListFile.Add(
      fpass + "\t" +
      fname + "\t");
    // ファイルサイズをnewListSizeに格納
    newListSize.Add(fi.Length);
  }
  // 2番目以降のファイルの場合
  else
  {
    string now = fpass + fname;
    string old =
    Path.GetDirectoryName(files[i - 1]) +
    Path.GetFileNameWithoutExtension(files[i - 1]);

    // もし同じパス+ファイル名が続いた場合
    if (now == old)
    {
      // ファイルサイズをチェック
      FileInfo fi = new FileInfo(files[i]);
      filesize = fi.Length;

      // 同じファイルが3度以上続いていない
      if (sameBool == false)
      {
        // 同じファイルの最初のListIndexを記憶
        sameId = newListFile.Count - 1;
        // 同じファイルの最初のListIndexにサイズを加算
        newListSize[sameId] += filesize;
        // フラグを立てる
        sameBool = true;
      }
      // 同じファイルが3度以上続いている
      else
      {
        // 同じファイルの最初のindexにサイズを加算
        newListSize[sameId] += filesize;
      }
    }
    else
    {
      // 連続フラグを解除
      sameBool = false;

      // ファイルサイズをチェック
      FileInfo fi = new FileInfo(files[i]);

      // ファイルパスをnewListFileに格納
      newListFile.Add(
        fpass + "\t" +
        fname + "\t");
      // ファイルサイズをnewListSizeに格納
      newListSize.Add(fi.Length);
    }
  }
}

ifとforを何度も入れ子にして無理矢理やりたいことはできたのですが
もう少しスマートな解決法があるのなら知りたいと思っています。
(ついでに言えば、何万ファイルというファイルに対して実行する必要があるため
 速いに越したことはありません)

「こういう方法もあるよ」「こういうやり方ならもっとお手軽だよ」など
何かアドバイスがありましたらぜひお願いします。m(_ _)m

A 回答 (2件)

Dictionary<string, long> dic = new Dictionary<string, long>();


を使ってみてはいかがでしょうか。
キー:ファイルパス
value:ファイルサイズの合計

そうすれば、i==0を見る必要はなくて、
long totalSize;
if ( dic.TryGetValue(fpass + "\\" + fname, out totalSize == true) {
totalSize += filesize;
} else {
totalSize = filesize;
}
dic.add(fpass + "\\" + fname, totalSize);
    • good
    • 0
この回答へのお礼

kikosiさん

ご回答ありがとうございます!
連想配列というのですね。
それだけの記述で済むというのは、まさに知りたいことでした!

ご提示頂いた記述ですと、同じKeyが来た際に
dic.AddでKeyと同じ内容のファイルパスを追加しようとして例外が起こりましたが
以下のような形にしたらいけました!

if (dic.TryGetValue(fpass + "\\" + fname, out fileSize) == true) {
totalSize += filesize;
dic[fpass + "\\" + fname] = totalSize;
} else {
totalSize = filesize;
dic.Add(fpass + "\\" + fname, totalSize);
}

連想配列、使いこなしていきたいと思います。
とても助かりました!
ありがとうございました。

お礼日時:2017/11/09 02:08

dictionaryを使用するのが最も簡単です。


以下は、コマンドボタンクリック時、テキストボックスに、ファイル情報を表示するサンプルです。
private void button1_Click(object sender, EventArgs e)
{
string[] files;
files = System.IO.Directory.GetFiles(@"d:\goo\data\削除ブック1", "*", System.IO.SearchOption.TopDirectoryOnly);
Dictionary<string, long> fdicT = new Dictionary<string, long>();
for (int i = 0; i < files.Length; i++)
{
string fpass = Path.GetDirectoryName(files[i]);
string fname = Path.GetFileNameWithoutExtension(files[i]);
FileInfo fi = new FileInfo(files[i]);
string key = fpass + "\\" + fname;
if (fdicT.ContainsKey(key) == false)
{ //最初なら0クリア
fdicT[key] = 0;
}
//サイズを加算
fdicT[key] += fi.Length;
}
//ディクショナリの全要素を処理
textBox1.Text = "";
foreach (var p in fdicT)
{
textBox1.Text += string.Format("{0},{1}", p.Key, p.Value) + "\r\n";
}
}
    • good
    • 0
この回答へのお礼

tatsu99さん

ご回答ありがとうございます!
お二人からDirectionalyをオススメされたことで
連想配列が今回のケースにマッチしているということがより実感できました。

それから、テキストボックスへの出力までカバー頂いてありがとうございます。
今回はkikosiさんから教えて頂いた方法をその後すぐ試してうまくいったのですが
tatsu99さんから教えて頂いた記述も試してみたいと思います!

お礼日時:2017/11/10 01:48

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!