Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
Dermian
0 / 0 / 2
Регистрация: 25.01.2014
Сообщений: 22
1

В заданном каталоге сравнить все файлы по содержимому и вывести список одинаковых

10.11.2015, 19:15. Просмотров 1189. Ответов 9
Метки нет (Все метки)

Здравствуйте, уважаемые форумчане! Есть задача: нужно в заданном каталоге сравнить все файлы по содержимому и вывести список одинаковых. Я начал делать так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 class SearchEquals
    {
        public List<string> _pathFiles = new List<string>();
 
 
        public void GetFiles(string path)
        {
             foreach (var item2 in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories))
            {
                _pathFiles.Add(item2);
            }
             _pathFiles.Sort();
        }
 
        public Dictionary<long, List<FileInfo>> GetLength()
        {
            Dictionary<long, List<FileInfo>> groupLengPair = new Dictionary<long, List<FileInfo>>();
            List<FileInfo> valueList= new List<FileInfo>();
 
            for (int i = 0; i < _pathFiles.Count; i++)
            {
                FileInfo fi = new FileInfo(_pathFiles[i]);
                for (int j = 0; j < _pathFiles.Count; j++)
                {
                    FileInfo fii=new FileInfo(_pathFiles[j]);
                    if(!_pathFiles[i].Equals(_pathFiles[j]))
                        {
                            if (fi.Length.Equals(fii.Length))
                             {
                                 if (groupLengPair.TryGetValue(fii.Length, out valueList))
                                 {
                                     valueList.Add(fii);
                                     groupLengPair[fii.Length]=valueList;
 
                                 }
                                 if (!groupLengPair.TryGetValue(fii.Length, out valueList))
                                 {
                                     valueList = new List<FileInfo>();
                                     valueList.Add(fii);
                                     groupLengPair.Add(fii.Length, valueList);
                                 }
                             }
                       }
                }
            }
            return groupLengPair;
        }
в Program:
C#
1
2
3
4
5
6
7
            string path = @"D:\desctop";
 
            SearchEquals search = new SearchEquals();
 
            search.GetFiles(path);
 
            search.GetLength();
столкнулся с проблемой что одни и те же файлы возвращает несколько раз.
Похоже что в один и тот же лист файлы добавляются несколько раз. Может кто свежим взглядом посмотрит и подскажет как можно сделать. Спасибо!
0
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.11.2015, 19:15
Ответы с готовыми решениями:

Найти все группы одинаковых файлов ненулевой длины в заданном каталоге и его подкаталогах
Ребята помоги-те, уже долго пытаюсь понять как это сделать, но получилось только отксанить папку......

Переименовать все файлы в заданном пользователем каталоге и во всех вложенных в него каталогах
Уважаемые господа программисты! Подскажите, как разрешить следующую проблему: переименовать все...

Переименовать все файлы в заданном каталоге
Помогите пожалуйста решить эту задачку: переименовать все файлы lab01.txt, Inf_lab02.txt … в...

В заданном каталоге найти и заархивировать все exe-файлы, имена которых начинаются на определённую строку
Всем привет. Сори может подобный вопрос часто обсуждался, но я чтот не нашел ответа в поиске. Мне...

Сравнить файл в каталоге со всеми остальными файлами в этом каталоге, результат вывести в txt-файл
Здравствуйте! Подскажите, как сравнить файл в каталоге со всеми остальными файлами(в этом...

9
Jupiter
Каратель
Эксперт С++
6577 / 3998 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
10.11.2015, 21:13 2
во внутреннем цикле поверяй i != j
0
Dermian
0 / 0 / 2
Регистрация: 25.01.2014
Сообщений: 22
10.11.2015, 22:01  [ТС] 3
там есть проверка, или Вы имели в виду проверять под одним из if ов?
0
MaxSlim
110 / 110 / 64
Регистрация: 03.06.2013
Сообщений: 584
10.11.2015, 23:54 4
Для начала предлагаю сделать так :
C#
1
List<string> allFiles = Directory.GetFiles(@"F:\tp", "*.*", SearchOption.AllDirectories).ToList();
0
10.11.2015, 23:54
Dermian
0 / 0 / 2
Регистрация: 25.01.2014
Сообщений: 22
11.11.2015, 02:14  [ТС] 5
так кроме того что сократится один метод, больше ничего полезного это вроде не дает...
0
OwenGlendower
Супер-модератор
Эксперт .NET
10933 / 9231 / 3929
Регистрация: 17.03.2014
Сообщений: 18,452
Записей в блоге: 1
Завершенные тесты: 2
11.11.2015, 04:21 6
Dermian, твой алгоритм длинный и очень неффективный. Каталог с 2500 файлами обрабатывал 15 минут. Вот вариант который сделал тоже самое меньше чем за секунду:
C#
1
2
3
List<FileInfo> files = new List<FileInfo>();
files.AddRange(new DirectoryInfo(path).EnumerateFiles("*.*", SearchOption.AllDirectories));
var length2files = files.GroupBy(fi => fi.Length).Where(g => g.Count()>1).ToDictionary(g => g.Key, g => g.ToList());
0
Dermian
0 / 0 / 2
Регистрация: 25.01.2014
Сообщений: 22
11.11.2015, 10:50  [ТС] 7
Спасибо , я знаю что через Linq выражения работает в разы быстрее, просто хотел разобраться как примерно можно сделать это в лоб, перебором
0
OwenGlendower
Супер-модератор
Эксперт .NET
10933 / 9231 / 3929
Регистрация: 17.03.2014
Сообщений: 18,452
Записей в блоге: 1
Завершенные тесты: 2
11.11.2015, 16:37 8
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

Цитата Сообщение от Dermian Посмотреть сообщение
я знаю что через Linq выражения работает в разы быстрее
Дело не в LINQ, а в неэффективной работе с памятью. Ты постоянно создаешь экземпляры FileInfo вместо того чтобы сделать это один раз. Всего это происходит N*(N+1) раз. Это создает большую нагрузку на сборщик мусора.

Кроме этого есть пара мелких моментов:

1) Сравнивать числа с помощью метода Equals нет смысла. Используй ==.
C#
1
2
3
4
5
// Вместо
if (fi.Length.Equals(fii.Length))
 
// Пишем
if (fi.Length == fii.Length)
2) В строке №30 ты вызываешь TryGetValue затем в строке №36 делаешь тоже самое только с отрицанием. Надо было использовать if/else.

3) Сортирврока по имени не несет пользы. Лучше отсортировать по длине. Тогда алгоритм можно будет сильно ускорить.

Ниже улучшенный (но все еще неправильно работающий) код. Твой вариант работал 5 минут, мой 1 секунду. Это даст тебе возможность нормально отлаживать код.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class SearchEquals
{
    public List<FileInfo> _pathFiles = new List<FileInfo>();
 
    public void GetFiles(string path)
    {
        _pathFiles.AddRange(new DirectoryInfo(path).EnumerateFiles("*.*", SearchOption.AllDirectories));
        //_pathFiles.Sort((f1, f2) => f1.FullName.CompareTo(f2.FullName));
    }
 
    public Dictionary<long, List<FileInfo>> GetLength()
    {
        Dictionary<long, List<FileInfo>> groupLengPair = new Dictionary<long, List<FileInfo>>();
        
        for (int i = 0; i < _pathFiles.Count; i++)
        {
            FileInfo fi = _pathFiles[i];
            for (int j = 0; j < _pathFiles.Count; j++)
            {
                FileInfo fii = _pathFiles[j];
                if (i == j || fi.Length != fii.Length) continue;
                
                List<FileInfo> valueList;
                if (groupLengPair.TryGetValue(fii.Length, out valueList))
                {
                    valueList.Add(fii);
                    groupLengPair[fii.Length]=valueList;
                }
                else
                {
                    valueList = new List<FileInfo>();
                    valueList.Add(fii);
                    groupLengPair.Add(fii.Length, valueList);
                }
            }
        }
        return groupLengPair;
    }
}


Цитата Сообщение от Dermian Посмотреть сообщение
просто хотел разобраться как примерно можно сделать это в лоб, перебором
Похвальное стремление. Бери вышепреведенный код и улучшай
2
Dermian
0 / 0 / 2
Регистрация: 25.01.2014
Сообщений: 22
11.11.2015, 21:21  [ТС] 9
Очень признателен за подробное разьяснение пошел шерстить матчасть
0
Dermian
0 / 0 / 2
Регистрация: 25.01.2014
Сообщений: 22
13.11.2015, 14:24  [ТС] 10
Помогли разобраться в чем была ошибка. Файлы в таком цикле сравниваются перекрестно, и поэтому один и тот же файл записывается 2 раза. Для того что бы один файл записывался один раз, нужен всего один цикл в котором в Dictionary будет записываться - в качестве ключа - размер файла, а значением будет List<FileInfo>. Потом просто исключить из Dictionary все значения по ключу которого хранятся List<FileInfo> с одним значением. На выходе получим отсортированный и сгруппированный по размерам список Dictionary.
Может кому то будет интересно.
0
13.11.2015, 14:24
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.11.2015, 14:24

Просмотреть с помощью boost::filesystem все файлы в рандомном каталоге, и вывести названия файлов
Доброго времени суток, помогите плиз. Как с помощью библиотеки boost::filesystem просмотреть все...

Найти файлы по маске в заданном каталоге
Здравствуйте всем. На Virtual Box поставил Ubuntu. В ней выполняю лабораторную работу. Дано...

Рекурсивно найти файлы в заданном каталоге содержащие заданную строку
Написать скрипт для поиска заданной пользователем строки во всех файлах заданного каталога и всех...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru