using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml; using Newtonsoft.Json; namespace MD5Create { public partial class MD5Create : Form { public MD5Create() { InitializeComponent(); // Initialize progress bar progressBar1.Minimum = 0; progressBar1.Maximum = 100; progressBar1.Value = 0; progressBar1.Step = 1; } // 程序启动前检查目录和版本号 private void Start_Button_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(Path1_Box.Text)) { MessageBox.Show("请先选择目录!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } if (string.IsNullOrWhiteSpace(textBox1.Text)) { MessageBox.Show("请输入版本号!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // Reset progress bar progressBar1.Value = 0; GenerateMD5Json(Path1_Box.Text); } private void Choose1_Button_Click(object sender, EventArgs e) { folderBrowserDialog1.Description = "请选择文件夹"; folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer; folderBrowserDialog1.ShowNewFolderButton = true; if (Path1_Box.Text.Length > 0) folderBrowserDialog1.SelectedPath = Path1_Box.Text; if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) { Path1_Box.Text = folderBrowserDialog1.SelectedPath; } } private void Exit_Button_Click(object sender, EventArgs e) { this.Close(); } // 计算 MD5 的值 private string MD5Generation(string filePath) { using (var md5 = MD5.Create()) using (var stream = File.OpenRead(filePath)) { byte[] hash = md5.ComputeHash(stream); return BitConverter.ToString(hash).Replace("-", "").ToLower(); } } // 获取目录中文件总数(用于进度计算) private int GetTotalFileCount(string directoryPath, string excludeFolder) { int count = Directory.GetFiles(directoryPath).Length; foreach (var dir in Directory.GetDirectories(directoryPath)) { if (dir.Equals(excludeFolder, StringComparison.OrdinalIgnoreCase)) continue; count += GetTotalFileCount(dir, excludeFolder); } return count; } // 生成目录结构的 json 表示 private Dictionary GenerateDirectoryJson(string directoryPath, string rootPath, int totalFiles, ref int processedFiles, string excludeFolder, string fileFolder) { var result = new Dictionary(); // 处理当前目录文件 foreach (var file in Directory.GetFiles(directoryPath)) { // 计算文件MD5 string fileMD5 = MD5Generation(file); string fileName = Path.GetFileName(file); result[fileName] = fileMD5; try { // 复制文件到fileFolder目录,以MD5值命名且不保留后缀 string destPath = Path.Combine(fileFolder, fileMD5); File.Copy(file, destPath, overwrite: true); Process_Box.Invoke((MethodInvoker)(() => { Process_Box.AppendText($"已复制: {file} -> {destPath}{Environment.NewLine}"); })); } catch (Exception ex) { Process_Box.Invoke((MethodInvoker)(() => { Process_Box.AppendText($"复制文件失败 {file}: {ex.Message}{Environment.NewLine}"); })); } // 更新进度条 processedFiles++; int progress = (int)((double)processedFiles / totalFiles * 100); progressBar1.Invoke((MethodInvoker)(() => { progressBar1.Value = Math.Min(progress, progressBar1.Maximum); })); // 显示处理路径 string relativePath = GetRelativePath(file, rootPath); Process_Box.Invoke((MethodInvoker)(() => { Process_Box.AppendText($".\\{relativePath}{Environment.NewLine}"); })); } // 递归处理子目录(自动跳过排除文件夹) foreach (var dir in Directory.GetDirectories(directoryPath)) { if (Path.GetFullPath(dir).Equals(Path.GetFullPath(excludeFolder), StringComparison.OrdinalIgnoreCase)) continue; string dirName = Path.GetFileName(dir); result[dirName] = GenerateDirectoryJson(dir, rootPath, totalFiles, ref processedFiles, excludeFolder, fileFolder); } return result; } // 获取相对路径 private string GetRelativePath(string fullPath, string basePath) { if (!basePath.EndsWith(Path.DirectorySeparatorChar.ToString())) basePath += Path.DirectorySeparatorChar; Uri baseUri = new Uri(basePath); Uri fullUri = new Uri(fullPath); return Uri.UnescapeDataString(baseUri.MakeRelativeUri(fullUri).ToString() .Replace('/', Path.DirectorySeparatorChar)); } // 生成 json 文件 private void GenerateMD5Json(string rootDirectory) { if (!Directory.Exists(rootDirectory)) { MessageBox.Show("指定的目录不存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { Process_Box.Clear(); progressBar1.Value = 0; Application.DoEvents(); // 存储MD5值 string md5FolderPath = Path.Combine(rootDirectory, "MD5"); Directory.CreateDirectory(md5FolderPath); // 存储MD5值对应的文件 string fileFolderPath = Path.Combine(md5FolderPath, "File"); Directory.CreateDirectory(fileFolderPath); int totalFiles = GetTotalFileCount(rootDirectory, md5FolderPath); int processedFiles = 0; // 如果文件数量为0,直接设置进度为100% if (totalFiles == 0) { progressBar1.Value = 100; Process_Box.AppendText("没有找到任何文件\n"); return; } var directoryStructure = GenerateDirectoryJson(rootDirectory, rootDirectory, totalFiles, ref processedFiles, md5FolderPath, fileFolderPath); // 创建包含版本号的新结构 var versionedStructure = new Dictionary { { "version", textBox1.Text.Trim() }, { "data", directoryStructure } }; // 序列化和保存JSON string json = JsonConvert.SerializeObject(versionedStructure, Newtonsoft.Json.Formatting.Indented); string jsonMD5 = CalculateMD5FromString(json); string outputPath = Path.Combine(md5FolderPath, "md5.json"); File.WriteAllText(outputPath, json); // 最终更新 progressBar1.Value = 100; Process_Box.AppendText($"\nmd5.json文件已生成在:{outputPath}\n"); Process_Box.AppendText($"JSON内容MD5校验值:{jsonMD5}"); Process_Box.ScrollToCaret(); } catch (Exception ex) { MessageBox.Show($"生成JSON文件时出错:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // 计算字符串的MD5值 private string CalculateMD5FromString(string input) { using (var md5 = MD5.Create()) { byte[] inputBytes = Encoding.UTF8.GetBytes(input); byte[] hashBytes = md5.ComputeHash(inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append(hashBytes[i].ToString("x2")); // 使用小写十六进制格式 } return sb.ToString(); } } } }