-
Notifications
You must be signed in to change notification settings - Fork 0
Initial commit #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Initial commit #26
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net7.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,90 @@ | ||||||
| using System.Text; | ||||||
| using System.Security.Cryptography; | ||||||
|
|
||||||
| namespace Md5; | ||||||
|
|
||||||
| public class MultiThreadMD5 | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
| { | ||||||
| /// <summary> | ||||||
| /// Calculating file using threads | ||||||
| /// </summary> | ||||||
| /// <param name="path">path where file</param> | ||||||
| /// <returns>md5 hash</returns> | ||||||
| public static async Task<byte[]> CalculateFile(string path) | ||||||
| { | ||||||
| if (!File.Exists(path)) | ||||||
| { | ||||||
| throw new FileNotFoundException(); | ||||||
| } | ||||||
| var fstream = File.OpenRead(path); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| using var md5 = MD5.Create(); | ||||||
| byte[] buffer = new byte[fstream.Length]; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| await fstream.ReadAsync(buffer, 0, buffer.Length); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Зачитывать весь файл в массив может быть хорошей идеей, если мы знаем, что у нас ОЧЕНЬ маленькие файлы и ОЧЕНЬ много оперативки. Поэтому у ComputeHash есть перегрузка, принимающая Stream (она сама вычитывает файл порциями и считает хеш поблочно). |
||||||
| return md5.ComputeHash(buffer); | ||||||
| } | ||||||
|
|
||||||
| private static async Task TakeFilesAndDirectoriesFromSubDirectories(string path, List<string> 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<string> listDirectoriesAndFiles) | ||||||
| { | ||||||
| listDirectoriesAndFiles.Add(path); | ||||||
| foreach (string file in Directory.GetFiles(path)) | ||||||
| { | ||||||
| listDirectoriesAndFiles.Add(file); | ||||||
| } | ||||||
| await TakeFilesAndDirectoriesFromSubDirectories(path, listDirectoriesAndFiles); | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Calculating md5 hash using threads | ||||||
| /// </summary> | ||||||
| public static async Task<byte[]> CalculateDirectory(string path) | ||||||
| { | ||||||
| if (!Directory.Exists(path)) | ||||||
| { | ||||||
| throw new DirectoryNotFoundException(); | ||||||
| } | ||||||
|
|
||||||
| var listAllDirectoriesAndFliles = new List<string>(); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| 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])); | ||||||
| } | ||||||
| }); | ||||||
|
Comment on lines
+66
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это не тот же самый алгоритм вычисления хеша, что просили в условии. Там хеш считается рекурсивно, тут просто по порядку хешируется всё содержимое директорий. |
||||||
|
|
||||||
| var listByte = new List<byte>(); | ||||||
|
|
||||||
| foreach (var element in arrayWithNumber) | ||||||
| { | ||||||
| foreach (var _byte in element) | ||||||
| { | ||||||
| listByte.Add(_byte); | ||||||
| } | ||||||
| } | ||||||
|
Comment on lines
+81
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Результатом по условию должен быть MD5-хеш, который 16-байтовый массив. А тут массив будет такого размера, какого получится. Ответ неправильный :) |
||||||
| return listByte.ToArray(); | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,88 @@ | ||||||
| using Md5; | ||||||
| using System.Diagnostics; | ||||||
|
|
||||||
| public class Program | ||||||
| { | ||||||
| public static async Task<int> Main() | ||||||
| { | ||||||
|
Comment on lines
+4
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не используйте Main, используйте top-level operators. |
||||||
| Console.WriteLine("Далее будет выполнено сравнение Md5 hash с использованием многопоточности и без неё"); | ||||||
| Console.WriteLine("Введите путь до дирректории"); | ||||||
| var pathToDirrectory = Console.ReadLine(); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| if (pathToDirrectory == null ) | ||||||
| { | ||||||
| throw new NullReferenceException(); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Никогда не кидайте NullReferenceException, оно всегда должно указывать на ошибку в коде (и кидаться .NET-машиной). |
||||||
| } | ||||||
| Stopwatch stopwatchForDirrectory = new Stopwatch(); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| 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; | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| using System.Text; | ||
| using System.Security.Cryptography; | ||
|
|
||
| namespace Md5; | ||
|
|
||
| public class SingleMd5 | ||
| { | ||
| /// <summary> | ||
| /// Calculating file by path | ||
| /// </summary> | ||
| /// <param name="path">Where file is lies</param> | ||
| /// <returns>md5 hash</returns> | ||
| 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); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Кажется, это можно было бы переиспользовать и в многопоточном варианте. |
||
| } | ||
|
|
||
| private static void TakeFilesAndDirectoriesFromSubDirectories(string path, List<string> 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<string> listDirectoriesAndFiles) | ||
| { | ||
| listDirectoriesAndFiles.Add(path); | ||
| foreach (string file in Directory.GetFiles(path)) | ||
| { | ||
| listDirectoriesAndFiles.Add(file); | ||
| } | ||
| TakeFilesAndDirectoriesFromSubDirectories(path, listDirectoriesAndFiles); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Calculating md5 hash using one thread | ||
| /// </summary> | ||
| public static byte[] CalculateDirectory(string path) | ||
| { | ||
| if (!Directory.Exists(path)) | ||
| { | ||
| throw new DirectoryNotFoundException(); | ||
| } | ||
|
|
||
| var listAllDirectoriesAndFliles = new List<string>(); | ||
| 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; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<DirectoryNotFoundException>(() => SingleMd5.CalculateDirectory(pathFile)); | ||
| } | ||
|
|
||
| [Test] | ||
| public void IsThrowExceptionWhenIncorrectPathDirrectoryInMultiThread() | ||
| { | ||
| Assert.ThrowsAsync<DirectoryNotFoundException>(() => MultiThreadMD5.CalculateDirectory(pathFile)); | ||
| } | ||
|
|
||
| [Test] | ||
| public void IsThrowExceptionWhenIncorrectPathFileInSingleThread() | ||
| { | ||
| Assert.Throws<FileNotFoundException>(() => SingleMd5.CalculateFile(pathDirectory + "/ttrt.txt")); | ||
| } | ||
|
|
||
| [Test] | ||
| public void IsThrowExceptionWhenIncorrectPathFileInMultiThread() | ||
| { | ||
| Assert.ThrowsAsync<FileNotFoundException>(() => MultiThreadMD5.CalculateFile(pathDirectory + "/ttrt.txt")); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно было бы использовать TestCaseSource, чтобы избежать копипаста. |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net7.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
|
|
||
| <IsPackable>false</IsPackable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> | ||
| <PackageReference Include="NUnit" Version="3.13.3" /> | ||
| <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" /> | ||
| <PackageReference Include="NUnit.Analyzers" Version="3.3.0" /> | ||
| <PackageReference Include="coverlet.collector" Version="3.1.2" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\MD5\MD5.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| global using NUnit.Framework; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 2 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лучше неймспейс в самом начале файла (после шапки с лицензией)