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