CreateMd5Json/Form1.cs

243 lines
9.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<string, object> GenerateDirectoryJson(string directoryPath, string rootPath, int totalFiles, ref int processedFiles, string excludeFolder, string fileFolder)
{
var result = new Dictionary<string, object>();
// 处理当前目录文件
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<string, object>
{
{ "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();
}
}
}
}