.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(); } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д