.NET 3.x OutOfMemoryException при получении большого количества файлов из каталога - C#
Формулировка задачи:
Доброго времени суток. Есть программа, которая в виде аргумента получает директорию, в которой она ищет и сравнивает все файлы и во всех поддиректориях. Проблема в том, что она слишком много жрет(30-40% ЦП и 400Мб ОЗУ, но так не всегда, это критические моменты). И если количество файлов уж очень большое(около 7к+) то вылетает выше написанное исключение. Могли бы вы подкинуть инфы об оптимизации кода на С#?
Решение задачи: «.NET 3.x OutOfMemoryException при получении большого количества файлов из каталога»
textual
Листинг программы
- using System;
- using System.Collections.Generic;
- using System.IO;
- namespace Compare
- {
- class myCompareFile
- {
- List<EqualFile> output = new List<EqualFile>();
- List<File> AllFiles = new List<File>();
- public List<EqualFile> CompareFile(string path)
- {
- // список файлов в этой директории
- List<string> files = new List<string>();
- // список папок в этой директории
- List<string> dirs = new List<string>();
- /*Шукаєм всі доступні файли*/
- try
- {
- /*Добавляю знайдені папки і файли в список*/
- files.AddRange(Directory.GetFiles(path));
- dirs.AddRange(Directory.GetDirectories(path));
- }
- catch (UnauthorizedAccessException ex)
- {
- Console.WriteLine(ex.Message);
- }
- catch (DirectoryNotFoundException ex)
- {
- Console.WriteLine(ex.Message);
- }
- // перебираем все новые файлы
- foreach (var newFile in files)
- {
- // получаем совпадения текущего файла с уже имеющимися в списке
- List<string> fromAll = CompareLength(newFile);
- if (fromAll.Count != 0) // если что-то там совпало...
- foreach (var item2 in fromAll)
- if (CompareHash(newFile, item2)) // то сравним хеши (ТС сравнит :)
- output.Add(new EqualFile(newFile, item2)); // если совпали хеши, то добавим в совпадения
- AllFiles.Add(new File(newFile, new FileInfo(newFile).Length)); // добавляем текущий файл ко всем
- }
- /*"Заглядаєм" за файлами в кожну директорію...*/
- foreach (string dir in dirs)
- {
- // прогуливаемся по директориям дальше
- CompareFile(dir);
- }
- return output;
- }
- /// <summary>
- /// Сравнивает по длинне текущий файл с имеющимеся в списке
- /// </summary>
- /// <param name="file"></param>
- /// <returns></returns>
- private List<string> CompareLength(string file)
- {
- List<string> result = new List<string>();
- foreach (var item in AllFiles)
- if (item.Length == new FileInfo(file).Length)
- result.Add(item.Path);
- return result;
- }
- /// <summary>
- /// Должна сравнивать файлы по хешу
- /// </summary>
- /// <param name="file1"></param>
- /// <param name="file2"></param>
- /// <returns>true если совпали</returns>
- private bool CompareHash(string file1, string file2)
- {
- int sizeBlock = 16;
- char[] buffer1 = new char[sizeBlock];
- char[] buffer2 = new char[sizeBlock];
- using (StreamReader sr1 = new StreamReader(file1), sr2 = new StreamReader(file2))
- {
- // предполагаю, если размеры файлов одинаковые,
- // то нет смысла проверять на конец sr1 и sr2
- long size = new FileInfo(file1).Length;
- for (int i = 0; i < size; i += sizeBlock)
- {
- try
- {
- sr1.ReadBlock(buffer1, i, sizeBlock);
- sr2.ReadBlock(buffer2, i, sizeBlock);
- }
- catch (Exception ex)
- {
- Console.WriteLine("Error: {0}", ex.Message);
- }
- // здесь должны сравниваться хеши, но это уже сделает автор :)
- for (int j = 0; j < buffer1.Length; ++j)
- if (buffer1[j] != buffer2[j])
- return false;
- if (size - i < sizeBlock)
- sizeBlock = (int)(size - i);
- }
- }
- return true;
- }
- }
- /// <summary>
- /// представляет класс файла.
- /// </summary>
- class File
- {
- public File() { }
- public File(string path, long length)
- {
- Path = path;
- Length = length;
- }
- public long Length { get; set; }
- public string Path { get; set; }
- public override string ToString()
- {
- return Path + "; Length = " + Length;
- }
- }
- /// <summary>
- /// класс для совпавших файлов
- /// тупо для удобства, можно заменить
- /// </summary>
- public class EqualFile
- {
- public EqualFile() { }
- public EqualFile(string file1, string file2)
- {
- File1 = file1;
- File2 = file2;
- }
- public string File1 { get; set;}
- public string File2 {get; set;}
- public override string ToString()
- {
- return File1 + " ===== " + File2;
- }
- }
- public class superMain
- {
- public static void Main()
- {
- myCompareFile mcf = new myCompareFile();
- List<EqualFile> path = mcf.CompareFile("D:\\obraz\\");
- foreach (var file in path)
- Console.WriteLine(file);
- Console.ReadLine();
- }
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д