.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();
        }
    }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 4.143 из 5
Похожие ответы