From 9381bb8804687840875606f33b790bea8156b1ee Mon Sep 17 00:00:00 2001 From: Lev Rusanov <30170278+JDM170@users.noreply.github.com> Date: Fri, 8 Nov 2024 23:01:42 +0700 Subject: [PATCH] Initial commit Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com> --- .gitignore | 5 +++ App.config | 6 +++ Program.cs | 74 +++++++++++++++++++++++++++++++ ProgressBar.cs | 90 ++++++++++++++++++++++++++++++++++++++ Properties/AssemblyInfo.cs | 33 ++++++++++++++ file_hash_checker.csproj | 54 +++++++++++++++++++++++ file_hash_checker.sln | 25 +++++++++++ 7 files changed, 287 insertions(+) create mode 100644 .gitignore create mode 100644 App.config create mode 100644 Program.cs create mode 100644 ProgressBar.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 file_hash_checker.csproj create mode 100644 file_hash_checker.sln diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93621e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.vs +bin/ +obj/ +packages/ +*.csproj.user diff --git a/App.config b/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..e5b02ea --- /dev/null +++ b/Program.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; + +namespace file_hash_checker +{ + internal class Program + { + private static string CalculateMD5(string data) + { + using (var md5 = MD5.Create()) + { + //using (var progress = new ProgressBar()) + //{ + // progress.Report((double)(stream.Position / stream.Length)); + //} + Console.Write("Расчет MD5... "); + using (var stream = File.OpenRead(data)) + md5.ComputeHash(stream); + Console.WriteLine("Готово."); + + StringBuilder sb = new StringBuilder(); + byte[] hash = md5.Hash; + for (int i = 0; i < hash.Length; i++) + sb.Append(hash[i].ToString("x2")); + + return sb.ToString(); + } + } + + private static string InputData(string message) + { + Console.WriteLine(message); + Console.Write("> "); + string data = Console.ReadLine().Trim(); + if (data.Length == 0 || data == string.Empty) + InputData(message); + return data; + } + + static void Main() + { + string filename = InputData("\nВведите путь до файла:"); + string remote = InputData("\nВведите путь до файла для сравнения (или путь до файла с хэшем или сам хэш):"); + Console.WriteLine(); + + string hash = CalculateMD5(filename); + bool result = false; + if (Regex.Match(remote, @"[a-zA-Z0-9]{32,}").Success) + result = hash == remote.ToLower(); + else if (File.Exists(remote)) + result = hash == CalculateMD5(remote); + else if (remote.EndsWith(".md5")) + { + if (!File.Exists(remote)) + { + Console.WriteLine("Файл не найден!"); + return; + } + var fileData = File.ReadAllText(remote); + Match match = Regex.Match(fileData, @"[a-zA-Z0-9]{32,}"); + if (match.Success) + result = hash == match.Value; + } + + Console.WriteLine("\nСовпадает: " + (result ? "Да" : "Нет")); + + Console.WriteLine("\nНажмите любую клавишу..."); + Console.ReadKey(); + } + } +} diff --git a/ProgressBar.cs b/ProgressBar.cs new file mode 100644 index 0000000..c8a9bc2 --- /dev/null +++ b/ProgressBar.cs @@ -0,0 +1,90 @@ +using System; +using System.Text; +using System.Threading; + +/// +/// An ASCII progress bar +/// +public class ProgressBar : IDisposable, IProgress { + private const int blockCount = 10; + private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8); + private const string animation = @"|/-\"; + + private readonly Timer timer; + + private double currentProgress = 0; + private string currentText = string.Empty; + private bool disposed = false; + private int animationIndex = 0; + + public ProgressBar() { + timer = new Timer(TimerHandler); + + // A progress bar is only for temporary display in a console window. + // If the console output is redirected to a file, draw nothing. + // Otherwise, we'll end up with a lot of garbage in the target file. + if (!Console.IsOutputRedirected) { + ResetTimer(); + } + } + + public void Report(double value) { + // Make sure value is in [0..1] range + value = Math.Max(0, Math.Min(1, value)); + Interlocked.Exchange(ref currentProgress, value); + } + + private void TimerHandler(object state) { + lock (timer) { + if (disposed) return; + + int progressBlockCount = (int) (currentProgress * blockCount); + int percent = (int) (currentProgress * 100); + string text = string.Format("[{0}{1}] {2,3}% {3}", + new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount), + percent, + animation[animationIndex++ % animation.Length]); + UpdateText(text); + + ResetTimer(); + } + } + + private void UpdateText(string text) { + // Get length of common portion + int commonPrefixLength = 0; + int commonLength = Math.Min(currentText.Length, text.Length); + while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength]) { + commonPrefixLength++; + } + + // Backtrack to the first differing character + StringBuilder outputBuilder = new StringBuilder(); + outputBuilder.Append('\b', currentText.Length - commonPrefixLength); + + // Output new suffix + outputBuilder.Append(text.Substring(commonPrefixLength)); + + // If the new text is shorter than the old one: delete overlapping characters + int overlapCount = currentText.Length - text.Length; + if (overlapCount > 0) { + outputBuilder.Append(' ', overlapCount); + outputBuilder.Append('\b', overlapCount); + } + + Console.Write(outputBuilder); + currentText = text; + } + + private void ResetTimer() { + timer.Change(animationInterval, TimeSpan.FromMilliseconds(-1)); + } + + public void Dispose() { + lock (timer) { + disposed = true; + UpdateText(string.Empty); + } + } + +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e28e97a --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Общие сведения об этой сборке предоставляются следующим набором +// набора атрибутов. Измените значения этих атрибутов для изменения сведений, +// связанные с этой сборкой. +[assembly: AssemblyTitle("Утилита для сверки контрольных сумм файлов")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("file_hash_checker")] +[assembly: AssemblyCopyright("Lev Rusanov © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми +// для компонентов COM. Если необходимо обратиться к типу в этой сборке через +// из модели COM задайте для атрибута ComVisible этого типа значение true. +[assembly: ComVisible(false)] + +// Следующий GUID представляет идентификатор typelib, если этот проект доступен из модели COM +[assembly: Guid("4fdab78e-f93e-4ddc-a787-b8ce6f14542f")] + +// Сведения о версии сборки состоят из указанных ниже четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Номер редакции +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/file_hash_checker.csproj b/file_hash_checker.csproj new file mode 100644 index 0000000..ddacd59 --- /dev/null +++ b/file_hash_checker.csproj @@ -0,0 +1,54 @@ + + + + + Debug + AnyCPU + {4FDAB78E-F93E-4DDC-A787-B8CE6F14542F} + Exe + file_hash_checker + file_hash_checker + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/file_hash_checker.sln b/file_hash_checker.sln new file mode 100644 index 0000000..73e6113 --- /dev/null +++ b/file_hash_checker.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35327.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "file_hash_checker", "file_hash_checker.csproj", "{4FDAB78E-F93E-4DDC-A787-B8CE6F14542F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4FDAB78E-F93E-4DDC-A787-B8CE6F14542F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FDAB78E-F93E-4DDC-A787-B8CE6F14542F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FDAB78E-F93E-4DDC-A787-B8CE6F14542F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FDAB78E-F93E-4DDC-A787-B8CE6F14542F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B85EDCB5-364F-4391-AF7B-0491EC8C2DCD} + EndGlobalSection +EndGlobal