プログラムの勉強を始めたばかりのものです。
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
No.1ベストアンサー
- 回答日時:
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);
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);
}
連想配列、使いこなしていきたいと思います。
とても助かりました!
ありがとうございました。
No.2
- 回答日時:
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";
}
}
tatsu99さん
ご回答ありがとうございます!
お二人からDirectionalyをオススメされたことで
連想配列が今回のケースにマッチしているということがより実感できました。
それから、テキストボックスへの出力までカバー頂いてありがとうございます。
今回はkikosiさんから教えて頂いた方法をその後すぐ試してうまくいったのですが
tatsu99さんから教えて頂いた記述も試してみたいと思います!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) pythonでクラスで複数のメソッドを利用する方法 2 2022/04/15 04:17
- Excel(エクセル) エクセル VBA For Next 繰り返しの書き方を教えてください 6 2022/09/01 14:11
- JavaScript clear機能を失わずにファイルアップロード機能を作成したい 3 2023/06/10 16:12
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- Visual Basic(VBA) 貼り付けた値が消えていく 以下はソースファイルの2番目のシートのB6から最終行を取得 ターゲットファ 2 2023/07/27 12:23
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Excel(エクセル) 【VBAファイル移動】2つのマクロを順に実行。1つ目のマクロが実行不可⇒2つ目が実行不可となる件 2 2022/07/29 12:17
- Visual Basic(VBA) 【VBA】印刷マクロのループ処理が反映されません 3 2022/08/09 02:15
- Excel(エクセル) エクセルVBA、間違っているコード内容を正して頂けませんか? エクセルワークシートに納品書を作ったの 2 2023/08/02 21:13
- Excel(エクセル) 【マクロ】フォルダAからダBへファイルを、ファイルの更新日時の条件で、1つづつ移動するには? 3 2022/08/25 09:56
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
SQLファイルの読み込み
-
C# ファイルを読み込みlistvie...
-
ファイルの文字コード
-
【ExcelVBA】300万件越えCSVか...
-
Excelマクロ 空白セルを無視し...
-
バッチ処理 特定の文字以降を...
-
Access VBA エラー2448について
-
[コンパイルエラー 修飾子が不...
-
CSVファイルの比較と結果の取得...
-
ファイル名を変数で書きこむfwr...
-
フォームのResizeイベントについて
-
EXCEL→CSV保存時のダブルクォー...
-
fortranでNAのあるデータを読み...
-
シート内容の文字列を置換してV...
-
ダブルコーテーション付きでCSV...
-
FileListBoxで出すものを絞り込...
-
【C#】 csvファイルをバイナリ...
-
eo(解凍ソフト)をバッチファイ...
-
verilog HDLについての質問です...
-
Rubyを使用してcsvファイルを処...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# ファイルを読み込みlistvie...
-
SQLファイルの読み込み
-
ファイルの読み込みデータを使...
-
【ruby】zipファイルデータをST...
-
ファイルサイズ
-
C# ファイルパスを格納した配列...
-
バッチ処理 特定の文字以降を...
-
【ExcelVBA】300万件越えCSVか...
-
ダブルコーテーション付きでCSV...
-
Excelマクロ 空白セルを無視し...
-
VBAでcsvファイルもシートもあ...
-
パイソンでテキストファイルが...
-
VBAで複数のCSVからレコードセ...
-
VBA テキストボックスを選択状...
-
fortranでNAのあるデータを読み...
-
ファイル名を変数で書きこむfwr...
-
[コンパイルエラー 修飾子が不...
-
CSVで余計な空行が入る
-
CSVデータの文字列置換
-
SQLでテキストボックスの文字を...
おすすめ情報