下面是一个基于 **Windows Forms (WinForms)** 的 C# 桌面应用程序,实现以下功能:
- 用户可以通过图形界面选择一个目标文件夹;
- 程序会读取该文件夹下的**所有一级子文件夹**;
- 统计每个一级子文件夹中包含的**所有文件数量(递归统计)**;
- 最终生成一个 `summary.txt` 文件,汇总结果;
- 提供清晰的 UI 交互:按钮、文本框、进度提示。
---
### ✅ 完整代码(使用 WinForms 实现)
#### 1. 创建项目(Visual Studio 或 .NET CLI)
```bash
dotnet new winforms -n FolderFileCounterApp
cd FolderFileCounterApp
```
然后替换 `Form1.cs` 内容如下:
```csharp
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace FolderFileCounterApp
{
public partial class MainForm : Form
{
private TextBox txtPath;
private Button btnBrowse;
private Button btnRun;
private ListBox listBoxResults;
private Label labelStatus;
public MainForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.Text = "文件夹文件统计工具";
this.Size = new Size(600, 500);
this.StartPosition = FormStartPosition.CenterScreen;
// 路径输入框
txtPath = new TextBox
{
Location = new Point(20, 20),
Size = new Size(400, 30)
};
// 浏览按钮
btnBrowse = new Button
{
Text = "浏览...",
Location = new Point(430, 20),
Size = new Size(80, 30)
};
btnBrowse.Click += BtnBrowse_Click;
// 运行按钮
btnRun = new Button
{
Text = "开始统计",
Location = new Point(20, 70),
Size = new Size(100, 30)
};
btnRun.Click += BtnRun_Click;
// 结果列表框
listBoxResults = new ListBox
{
Location = new Point(20, 120),
Size = new Size(540, 250),
HorizontalScrollbar = true
};
// 状态标签
labelStatus = new Label
{
Text = "请选择一个文件夹。",
Location = new Point(20, 400),
Size = new Size(540, 30),
ForeColor = Color.Blue
};
// 添加控件
this.Controls.Add(txtPath);
this.Controls.Add(btnBrowse);
this.Controls.Add(btnRun);
this.Controls.Add(listBoxResults);
this.Controls.Add(labelStatus);
}
private void BtnBrowse_Click(object sender, EventArgs e)
{
using (var dialog = new FolderBrowserDialog())
{
dialog.Description = "请选择要统计的文件夹";
if (dialog.ShowDialog() == DialogResult.OK)
{
txtPath.Text = dialog.SelectedPath;
labelStatus.Text = $"已选择路径:{dialog.SelectedPath}";
}
}
}
private void BtnRun_Click(object sender, EventArgs e)
{
string rootPath = txtPath.Text.Trim();
if (string.IsNullOrEmpty(rootPath) || !Directory.Exists(rootPath))
{
MessageBox.Show("请先选择一个有效的文件夹!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
labelStatus.Text = "正在统计,请稍候...";
Application.DoEvents(); // 让界面刷新
var results = new Dictionary<string, int>();
string[] subDirs = Directory.GetDirectories(rootPath);
foreach (string dir in subDirs)
{
string dirName = new DirectoryInfo(dir).Name;
int count = CountAllFiles(dir);
results[dirName] = count;
listBoxResults.Items.Add($"{dirName}: {count} 个文件");
}
// 生成 summary.txt
string outputFilePath = Path.Combine(rootPath, "summary.txt");
WriteSummaryToFile(results, outputFilePath);
labelStatus.Text = $"✅ 统计完成!结果已保存至:\n{outputFilePath}";
MessageBox.Show($"统计完成!共分析 {results.Count} 个子文件夹。\n结果已保存为:{outputFilePath}", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
labelStatus.Text = "❌ 出错:" + ex.Message;
MessageBox.Show("发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 递归统计指定目录中的所有文件数量
/// </summary>
private int CountAllFiles(string path)
{
int count = 0;
try
{
count += Directory.GetFiles(path).Length;
foreach (string dir in Directory.GetDirectories(path))
{
count += CountAllFiles(dir);
}
}
catch (UnauthorizedAccessException)
{
// 忽略无权限访问的目录
}
catch (IOException)
{
// 忽略路径过长或被占用的情况
}
return count;
}
/// <summary>
/// 写入汇总文件
/// </summary>
private void WriteSummaryToFile(Dictionary<string, int> results, string filePath)
{
using (var writer = new StreamWriter(filePath, false, System.Text.Encoding.UTF8))
{
writer.WriteLine("=== 文件夹文件数量汇总 ===");
writer.WriteLine($"生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
writer.WriteLine(new string('-', 40));
foreach (var kvp in results)
{
writer.WriteLine($"{kvp.Key,-25} : {kvp.Value,8} 个文件");
}
writer.WriteLine(new string('-', 40));
writer.WriteLine($"总计 {results.Count} 个子文件夹,文件总数: {GetTotal(results)}");
}
}
private long GetTotal(Dictionary<string, int> results)
{
long total = 0;
foreach (var v in results.Values) total += v;
return total;
}
}
// Program.cs 启动入口
internal static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
```
---
### 📦 发布为独立 `.exe` 可执行程序
在项目根目录运行以下命令,生成单文件 `.exe`:
```bash
dotnet publish -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
```
生成路径:
```
bin/Release/net6.0/win-x64/publish/FolderFileCounterApp.exe
```
你可以将这个 `.exe` 分发给他人使用,无需安装开发环境。
---
### 🖼️ 界面说明
| 控件 | 功能 |
|------|------|
| 文本框 + 浏览按钮 | 允许用户选择目标文件夹 |
| “开始统计”按钮 | 触发扫描和统计过程 |
| 列表框 | 显示每个子文件夹及其文件数量 |
| 状态标签 | 显示当前状态或提示信息 |
---
### 📝 输出示例:`summary.txt`
```text
=== 文件夹文件数量汇总 ===
生成时间: 2025-04-05 15:20:33
----------------------------------------
Documents : 152 个文件
Images : 1024 个文件
Logs : 87 个文件
Videos : 45 个文件
----------------------------------------
总计 4 个子文件夹,文件总数: 1308
```
---
### ✅ 特性亮点
- 图形化操作,适合非技术人员使用;
- 支持中文路径与特殊字符(UTF-8 编码);
- 自动处理权限异常、路径错误;
- 友好提示与错误弹窗;
- 不依赖第三方库(纯原生 WinForms + System.IO);
---
###