From a9498259495f98f72ecf4efe7e698e1dd998d924 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 30 Nov 2023 17:08:33 +0300 Subject: [PATCH] Initial commit --- MD5/MD5.sln | 31 +++++++ MD5/MD5/MD5.csproj | 10 +++ MD5/MD5/MultiThreadMD5.cs | 90 +++++++++++++++++++ MD5/MD5/Program.cs | 88 ++++++++++++++++++ MD5/MD5/SingleThreadMD5.cs | 77 ++++++++++++++++ MD5/TestsMD5/TestsMD5.cs | 51 +++++++++++ MD5/TestsMD5/TestsMD5.csproj | 23 +++++ MD5/TestsMD5/Usings.cs | 1 + .../bin/Debug/net7.0/ForTests/file1.txt | 1 + .../bin/Debug/net7.0/ForTests/file2.txt | 1 + .../Debug/net7.0/ForTests/folder2/file3.txt | 1 + 11 files changed, 374 insertions(+) create mode 100644 MD5/MD5.sln create mode 100644 MD5/MD5/MD5.csproj create mode 100644 MD5/MD5/MultiThreadMD5.cs create mode 100644 MD5/MD5/Program.cs create mode 100644 MD5/MD5/SingleThreadMD5.cs create mode 100644 MD5/TestsMD5/TestsMD5.cs create mode 100644 MD5/TestsMD5/TestsMD5.csproj create mode 100644 MD5/TestsMD5/Usings.cs create mode 100644 MD5/TestsMD5/bin/Debug/net7.0/ForTests/file1.txt create mode 100644 MD5/TestsMD5/bin/Debug/net7.0/ForTests/file2.txt create mode 100644 MD5/TestsMD5/bin/Debug/net7.0/ForTests/folder2/file3.txt diff --git a/MD5/MD5.sln b/MD5/MD5.sln new file mode 100644 index 0000000..c8dc028 --- /dev/null +++ b/MD5/MD5.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33403.182 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MD5", "MD5\MD5.csproj", "{A1FB78F7-7A8A-4EC2-AB83-C049DF18BB6C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsMD5", "TestsMD5\TestsMD5.csproj", "{330AFC94-ABE1-4802-8712-134A7848F562}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A1FB78F7-7A8A-4EC2-AB83-C049DF18BB6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A1FB78F7-7A8A-4EC2-AB83-C049DF18BB6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1FB78F7-7A8A-4EC2-AB83-C049DF18BB6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A1FB78F7-7A8A-4EC2-AB83-C049DF18BB6C}.Release|Any CPU.Build.0 = Release|Any CPU + {330AFC94-ABE1-4802-8712-134A7848F562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {330AFC94-ABE1-4802-8712-134A7848F562}.Debug|Any CPU.Build.0 = Debug|Any CPU + {330AFC94-ABE1-4802-8712-134A7848F562}.Release|Any CPU.ActiveCfg = Release|Any CPU + {330AFC94-ABE1-4802-8712-134A7848F562}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3D47FDE2-DD6A-4102-8AE7-947763D5FA8D} + EndGlobalSection +EndGlobal diff --git a/MD5/MD5/MD5.csproj b/MD5/MD5/MD5.csproj new file mode 100644 index 0000000..f02677b --- /dev/null +++ b/MD5/MD5/MD5.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/MD5/MD5/MultiThreadMD5.cs b/MD5/MD5/MultiThreadMD5.cs new file mode 100644 index 0000000..a94f524 --- /dev/null +++ b/MD5/MD5/MultiThreadMD5.cs @@ -0,0 +1,90 @@ +using System.Text; +using System.Security.Cryptography; + +namespace Md5; + +public class MultiThreadMD5 +{ + /// + /// Calculating file using threads + /// + /// path where file + /// md5 hash + public static async Task CalculateFile(string path) + { + if (!File.Exists(path)) + { + throw new FileNotFoundException(); + } + var fstream = File.OpenRead(path); + using var md5 = MD5.Create(); + byte[] buffer = new byte[fstream.Length]; + await fstream.ReadAsync(buffer, 0, buffer.Length); + return md5.ComputeHash(buffer); + } + + private static async Task TakeFilesAndDirectoriesFromSubDirectories(string path, List listDirectoriesAndFiles) + { + var allDirectories = Directory.GetDirectories(path); + foreach (string directory in allDirectories) + { + listDirectoriesAndFiles.Add(directory); + var allFiles = Directory.GetFiles(directory); + + foreach (string file in allFiles) + { + listDirectoriesAndFiles.Add(file); + } + await TakeFilesAndDirectoriesFromSubDirectories(directory, listDirectoriesAndFiles); + } + } + + private static async Task TakeFilesAndDirectoriesFromDirectory(string path, List listDirectoriesAndFiles) + { + listDirectoriesAndFiles.Add(path); + foreach (string file in Directory.GetFiles(path)) + { + listDirectoriesAndFiles.Add(file); + } + await TakeFilesAndDirectoriesFromSubDirectories(path, listDirectoriesAndFiles); + } + + /// + /// Calculating md5 hash using threads + /// + public static async Task CalculateDirectory(string path) + { + if (!Directory.Exists(path)) + { + throw new DirectoryNotFoundException(); + } + + var listAllDirectoriesAndFliles = new List(); + await TakeFilesAndDirectoriesFromDirectory(path, listAllDirectoriesAndFliles); + var arrayList = listAllDirectoriesAndFliles.ToArray(); + var arrayWithNumber = new byte[arrayList.Length][]; + Parallel.For(0, arrayList.Length, i => + { + using var md5 = MD5.Create(); + if (File.Exists(arrayList[i])) + { + arrayWithNumber[i] = CalculateFile(arrayList[i]).Result; + } + else + { + arrayWithNumber[i] = md5.ComputeHash(Encoding.UTF8.GetBytes(arrayList[i])); + } + }); + + var listByte = new List(); + + foreach (var element in arrayWithNumber) + { + foreach (var _byte in element) + { + listByte.Add(_byte); + } + } + return listByte.ToArray(); + } +} \ No newline at end of file diff --git a/MD5/MD5/Program.cs b/MD5/MD5/Program.cs new file mode 100644 index 0000000..c91f450 --- /dev/null +++ b/MD5/MD5/Program.cs @@ -0,0 +1,88 @@ +using Md5; +using System.Diagnostics; + +public class Program +{ + public static async Task Main() + { + Console.WriteLine("Далее будет выполнено сравнение Md5 hash с использованием многопоточности и без неё"); + Console.WriteLine("Введите путь до дирректории"); + var pathToDirrectory = Console.ReadLine(); + if (pathToDirrectory == null ) + { + throw new NullReferenceException(); + } + Stopwatch stopwatchForDirrectory = new Stopwatch(); + stopwatchForDirrectory.Start(); + try + { + var hash = SingleMd5.CalculateDirectory(pathToDirrectory); + } + catch (DirectoryNotFoundException) + { + Console.WriteLine("Проблемы с путём к дирректории"); + stopwatchForDirrectory.Stop(); + return 0; + } + stopwatchForDirrectory.Stop(); + Console.WriteLine(); + Console.Write("Время исполнения подсчёта hash с использованием 1 потока: "); + Console.WriteLine(stopwatchForDirrectory.ElapsedMilliseconds); + stopwatchForDirrectory.Reset(); + stopwatchForDirrectory.Start(); + try + { + var hash = await MultiThreadMD5.CalculateDirectory(pathToDirrectory); + } + catch (DirectoryNotFoundException) + { + Console.WriteLine("Проблемы с путём к дирректории"); + stopwatchForDirrectory.Stop(); + return 0; + } + stopwatchForDirrectory.Stop(); + Console.Write("Время исполнения подсчёта hash с использованием нескольких потоков: "); + Console.WriteLine(stopwatchForDirrectory.ElapsedMilliseconds); + + Console.WriteLine(); + Console.WriteLine("Ввдеите путь до файла"); + var pathToFile = Console.ReadLine(); + if (pathToFile == null) + { + throw new NullReferenceException(); + } + Stopwatch stopwatchForFile = new Stopwatch(); + stopwatchForFile.Start(); + try + { + var hash = SingleMd5.CalculateFile(pathToFile); + } + catch (FileNotFoundException) + { + Console.WriteLine("Проблемы с путём к файлу"); + stopwatchForDirrectory.Stop(); + return 0; + } + stopwatchForFile.Stop(); + Console.WriteLine(); + Console.Write("Время исполнения подсчёта hash с использованием 1 потока: "); + Console.WriteLine(stopwatchForFile.ElapsedMilliseconds); + stopwatchForFile.Reset(); + stopwatchForFile.Start(); + try + { + var hash = await MultiThreadMD5.CalculateFile(pathToFile); + } + catch (FileNotFoundException) + { + Console.WriteLine("Проблемы с путём к файлу"); + stopwatchForDirrectory.Stop(); + return 0; + } + stopwatchForFile.Stop(); + Console.Write("Время исполнения подсчёта hash с использованием нескольких потоков: "); + Console.WriteLine(stopwatchForFile.ElapsedMilliseconds); + + return 0; + } +} \ No newline at end of file diff --git a/MD5/MD5/SingleThreadMD5.cs b/MD5/MD5/SingleThreadMD5.cs new file mode 100644 index 0000000..f4fb29d --- /dev/null +++ b/MD5/MD5/SingleThreadMD5.cs @@ -0,0 +1,77 @@ +using System.Text; +using System.Security.Cryptography; + +namespace Md5; + +public class SingleMd5 +{ + /// + /// Calculating file by path + /// + /// Where file is lies + /// md5 hash + public static byte[] CalculateFile(string path) + { + if (!File.Exists(path)) + { + throw new FileNotFoundException(); + } + var fstream = File.OpenRead(path); + using var md5 = MD5.Create(); + return md5.ComputeHash(fstream); + } + + private static void TakeFilesAndDirectoriesFromSubDirectories(string path, List listDirectoriesAndFiles) + { + var allDirectories = Directory.GetDirectories(path); + foreach (string directory in allDirectories) + { + listDirectoriesAndFiles.Add(directory); + var allFiles = Directory.GetFiles(directory); + + foreach (string file in allFiles) + { + listDirectoriesAndFiles.Add(file); + } + TakeFilesAndDirectoriesFromSubDirectories(directory, listDirectoriesAndFiles); + } + } + + private static void TakeFilesAndDirectoriesFromDirectory(string path, List listDirectoriesAndFiles) + { + listDirectoriesAndFiles.Add(path); + foreach (string file in Directory.GetFiles(path)) + { + listDirectoriesAndFiles.Add(file); + } + TakeFilesAndDirectoriesFromSubDirectories(path, listDirectoriesAndFiles); + } + + /// + /// Calculating md5 hash using one thread + /// + public static byte[] CalculateDirectory(string path) + { + if (!Directory.Exists(path)) + { + throw new DirectoryNotFoundException(); + } + + var listAllDirectoriesAndFliles = new List(); + TakeFilesAndDirectoriesFromDirectory(path, listAllDirectoriesAndFliles); + using var md5 = MD5.Create(); + var result = new byte[0]; + foreach (var fileOrDirectory in listAllDirectoriesAndFliles) + { + if (File.Exists(fileOrDirectory)) + { + result = result.Concat(CalculateFile(fileOrDirectory)).ToArray(); + } + else + { + result = result.Concat(md5.ComputeHash(Encoding.UTF8.GetBytes(fileOrDirectory))).ToArray(); + } + } + return result; + } +} \ No newline at end of file diff --git a/MD5/TestsMD5/TestsMD5.cs b/MD5/TestsMD5/TestsMD5.cs new file mode 100644 index 0000000..e84b437 --- /dev/null +++ b/MD5/TestsMD5/TestsMD5.cs @@ -0,0 +1,51 @@ +namespace TestsMD5; + +using Md5; + +public class Tests +{ + private string pathDirectory = Path.Combine(TestContext.CurrentContext.TestDirectory, "ForTests"); + private string pathFile = Path.Combine(TestContext.CurrentContext.TestDirectory, "ForTests", "file1.txt"); + + [Test] + public async Task AreTheResultsSameWithDirectories() + { + var hashMultiThreads = await MultiThreadMD5.CalculateDirectory(pathDirectory); + var hashSingleThread = SingleMd5.CalculateDirectory(pathDirectory); + + Assert.That(hashMultiThreads, Is.EquivalentTo(hashSingleThread)); + } + + [Test] + public async Task AreTheResultsSameWithFiles() + { + var hashMultiThreads = await MultiThreadMD5.CalculateFile(pathFile); + var hashSingleThread = SingleMd5.CalculateFile(pathFile); + + Assert.That(hashMultiThreads, Is.EquivalentTo(hashSingleThread)); + } + + [Test] + public void IsThrowExceptionWhenIncorrectPathDirrectoryInSingleThread() + { + Assert.Throws(() => SingleMd5.CalculateDirectory(pathFile)); + } + + [Test] + public void IsThrowExceptionWhenIncorrectPathDirrectoryInMultiThread() + { + Assert.ThrowsAsync(() => MultiThreadMD5.CalculateDirectory(pathFile)); + } + + [Test] + public void IsThrowExceptionWhenIncorrectPathFileInSingleThread() + { + Assert.Throws(() => SingleMd5.CalculateFile(pathDirectory + "/ttrt.txt")); + } + + [Test] + public void IsThrowExceptionWhenIncorrectPathFileInMultiThread() + { + Assert.ThrowsAsync(() => MultiThreadMD5.CalculateFile(pathDirectory + "/ttrt.txt")); + } +} \ No newline at end of file diff --git a/MD5/TestsMD5/TestsMD5.csproj b/MD5/TestsMD5/TestsMD5.csproj new file mode 100644 index 0000000..e8ca5b8 --- /dev/null +++ b/MD5/TestsMD5/TestsMD5.csproj @@ -0,0 +1,23 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/MD5/TestsMD5/Usings.cs b/MD5/TestsMD5/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/MD5/TestsMD5/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/MD5/TestsMD5/bin/Debug/net7.0/ForTests/file1.txt b/MD5/TestsMD5/bin/Debug/net7.0/ForTests/file1.txt new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/MD5/TestsMD5/bin/Debug/net7.0/ForTests/file1.txt @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/MD5/TestsMD5/bin/Debug/net7.0/ForTests/file2.txt b/MD5/TestsMD5/bin/Debug/net7.0/ForTests/file2.txt new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/MD5/TestsMD5/bin/Debug/net7.0/ForTests/file2.txt @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/MD5/TestsMD5/bin/Debug/net7.0/ForTests/folder2/file3.txt b/MD5/TestsMD5/bin/Debug/net7.0/ForTests/folder2/file3.txt new file mode 100644 index 0000000..e440e5c --- /dev/null +++ b/MD5/TestsMD5/bin/Debug/net7.0/ForTests/folder2/file3.txt @@ -0,0 +1 @@ +3 \ No newline at end of file