Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9

Ускорить алгоритм составления списка файлов данной директории

26.08.2016, 14:21. Показов 1559. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.
Есть папка с файлами(462166 штук), как мне быстро получить их список, а следовательно и их количество?
Вот, собственно, мой код, который работает где-то 30 минут:
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
    TSearchRec SR;
    TSearchRec tFileInfo;
    int a(0);
    if(FindFirst(ExtractFileDir(Application->ExeName) + "\\date\\images\\*.*", faDirectory, SR) == 0)
    {
        do
        {
            if( (SR.Attr & faDirectory) == faDirectory &&
                SR.Name != "." &&
                SR.Name != ".."
            )
            {
                if(FindFirst(ExtractFileDir(Application->ExeName) + "\\date\\images" + SR.Name + "\\*.*", faAnyFile, tFileInfo) == 0)
                {
                    do
                    {
                        // Исключаем корневую
                        if( tFileInfo.Name != "." &&
                            tFileInfo.Name != ".." &&
                            (tFileInfo.Attr & faDirectory) != faDirectory
                        ) // "." - ссылка на саму себя, ".." - родительская папка
                        {
                            a++;
                        }
                    }
                    while(FindNext(tFileInfo) == 0); // Цикл продолжается, пока FindNext что-то находит.
                }
                ComboBox7->Items->Add(SR.Name + "(" + a + ")");
                a = 0;
            }
        }
        while (FindNext(SR) == 0);
    }
    ComboBox7->ItemIndex = 0;
    FindClose(SR);
    FindClose(tFileInfo);
    List->Clear();
    delete List;
Этот код ищет подпапки, в которых и считает количество файлов.

Буду признателен за любую помощь.
Изображения
 
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.08.2016, 14:21
Ответы с готовыми решениями:

Как получить список файлов в данной директории?
Нужно получить список файлов, находящийся в некоторой директории (и поместить его в массив строк). Как это можно сделать? В справке на...

FTP: получение списка файлов из потока. Как вывести список файлов из директории?
доброго времени суток. пытаюсь написать свой FTP-клиент. отправил серверу команду LIST, и в ответ он выдал "ок. успешно" ...

Получить названия всех файлов с данным расширением в данной директории
Мне нужно, чтобы моя программа при запуске получала имена всех файлов с расширением .mmf, лежащих в директории /Files. Как это можно...

23
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
26.08.2016, 14:34
Мне кажется, что поиск долго идет из-за этой строки:
C++
1
ComboBox7->Items->Add(SR.Name + "(" + a + ")");
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
26.08.2016, 14:50  [ТС]
d7d1cd, а мне кажется, что поиск долго идет как раз из-за составления списка файлов(их подсчета).
Дело в том, что я тестирую на одной папке с файлами(см скрин) и, следовательно, строка
C++
1
ComboBox7->Items->Add(SR.Name + "(" + a + ")");
выполняется только один раз. Вывод? Правильно, тормозит не тут!
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
26.08.2016, 14:54
Gdasar, верно, верно! Проглядел я...
0
 Аватар для BOGG ART
592 / 459 / 147
Регистрация: 09.12.2013
Сообщений: 2,385
Записей в блоге: 2
26.08.2016, 14:55
Скорость может зависеть от самих файлов и средней глубины вложенности. Это ничем не ускоряется.
А чтоб обращение к ComboBox7 было нормально надо кое-какие действия:
  • Сперва его надо очистить - вдруг пользователь пятый раз тыкает на кнопку "поиск файлов" или типа неё.
  • Потом сделать либо BeginUpdate() либо невидимым - смотря какая версия Билдера у вас.
  • Уже тогда заполнять данными.
  • А в самом конце сделать EndUpdate() / видимым.
1
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
26.08.2016, 15:00  [ТС]
Сперва его надо очистить - вдруг пользователь пятый раз тыкает на кнопку "поиск файлов" или типа неё.
Это делается. Про остальное учту - что-то забыл про BeginUpdate() и EndUpdate()

Кстати, забыл написать, этот код выполняется при запуске программы( в FormCreate) - может в этом затык?
0
 Аватар для BOGG ART
592 / 459 / 147
Регистрация: 09.12.2013
Сообщений: 2,385
Записей в блоге: 2
26.08.2016, 15:08
а... Вложенность нуль? Тоже не заметил... Но файлов правда дофига, мне просто не на чем проверить время поиска.
А если на АПИ переписать будет быстрее?

FormCreate или нет не должно влиять. Но вы же можете это легко проверить. А всё-таки версия-то Билдера какая?
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
26.08.2016, 15:24  [ТС]
Версия - XE8. Да, от FormCreate не зависит.
Вот такой путь до папки с картинками:
Code
1
E:\1_project\Project\Win32\Debug\date\images\Work_dir
Добавлено через 3 минуты
Кстати, про скорость.
Если нажать свойство папки, то вся инфа собирается менее чем за минуту.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
26.08.2016, 15:25
Судя по прикрепленной картинке, все файлы у Вас хранятся в одной папке (файлов: 462166, папок: 0). Это так?
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
26.08.2016, 15:27  [ТС]
Цитата Сообщение от d7d1cd Посмотреть сообщение
Это так?
Так.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
26.08.2016, 15:33
Цитата Сообщение от Gdasar Посмотреть сообщение
Кстати, про скорость.
Если нажать свойство папки, то вся инфа собирается менее чем за минуту.
Если винда так быстро ищет файлы, значит и мы сможем . Наверное. Но только, как сказал BOGG ART, через АПИ.
1
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
26.08.2016, 15:45
Пробуем методы TDirectory, они работают быстрее ручного перебора через FindFirst/FindNext. Да, кстати, тебе-таки нужен список, или только количество?
0
 Аватар для BOGG ART
592 / 459 / 147
Регистрация: 09.12.2013
Сообщений: 2,385
Записей в блоге: 2
26.08.2016, 15:48
По идее количество файлов в директории может где-то храниться в готовом виде.
Кажется были какие-то необычные функции, но не помню как называются.

Просто как тест - сколько будет думать если в консоли набрать:
Bash
1
DIR "E:\1_project\Project\Win32\Debug\date\images\Work_dir"
Добавлено через 30 секунд
Судя по всему - просто количество.
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
26.08.2016, 15:57  [ТС]
Я тут погуглил : http://www.realcoding.net/arti... ast-2.html

И мне почему-то кажется, что мой код как раз и написан с помощью WinAPI. Или нет?

Добавлено через 1 минуту
volvo, сперва нужна информация о количестве файлов, а потом нужен и их список.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
26.08.2016, 16:05
Лучший ответ Сообщение было отмечено Gdasar как решение

Решение

C++
1
2
3
#include <IOUtils.hpp>
// ...
    ShowMessage(IntToStr(TDirectory::GetFiles("D:\\test\\largest").Length)); // 170000 файлов
, посчитало за 1.5 секунды ... И количество и список, если что...
1
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
26.08.2016, 16:20
Цитата Сообщение от Gdasar Посмотреть сообщение
И мне почему-то кажется, что мой код как раз и написан с помощью WinAPI. Или нет?
Через API это вот так:
C++
1
2
3
4
5
6
7
         WIN32_FIND_DATA Data;
     HANDLE Search=FindFirstFile((Path+"*.dll").c_bstr(),&Data);
     if (Search)
     do{
               // делаем с найденным чего надо
     }while(FindNextFile(Search,&Data));
     FindClose(Search);
Но у тех функций что ты пользуешь это все явно напрямую под капотом потому таким способом задержки пытаться устранить без смысла.
Цитата Сообщение от Gdasar Посмотреть сообщение
сперва нужна информация о количестве файлов, а потом нужен и их список.
Сама директория это файл содержащий список файлов с атрибутами и т.п. Открой ее как файл и прочитай по записям. Сэкономишь очень много времени которое WinAPI тратит на фильтрацию имен. Ну правда придется формат структуры описывающей файл расковырять.
1
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
26.08.2016, 16:30  [ТС]
volvo, круто
У меня где-то 30 секунд думал.
А как теперь список файлов вытащить так же быстро?
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
26.08.2016, 16:44
Цитата Сообщение от Gdasar Посмотреть сообщение
У меня где-то 30 секунд думал.
Кстати инфа к размышлению насчет скорости - папочка на HDD 25GB 125 тыс файлов 32 тыс папок - подсчет проводником минуты 2-3. Копия той же папки на SSD - 1-2 секунды. т.е. очень многое от скорости диска зависит при сканировании через винапи причем от cylinder-to-cylinder seek что говорит о том что WinApi производит чтение не всего файла директории сразу а по записям при вызове FindNext. Соответственно неплохо бы было считать весь файл директории сразу и ковыряться в ней уже в памяти.
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
26.08.2016, 16:46  [ТС]
Fulcrum_013, а как считать директорию, как файл?

Добавлено через 39 секунд
Цитата Сообщение от BOGG ART Посмотреть сообщение
Просто как тест - сколько будет думать если в консоли набрать:
Очень долго думал, закрыл консольку.
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
26.08.2016, 16:54
Цитата Сообщение от Gdasar Посмотреть сообщение
а как считать директорию, как файл?
Открываешь ее просто как файл. Указываешь имя директории при открытии и она открыта как обычный бинарный файл. К примеру new TFileStream("c:\\windows",faOpenRead); потом читаешь в буфер паямти весь файл. потом уже ковыряешь.
Чтобы долго с буфером не морочится можно вот так:
C++
1
2
TMemoryStream *Dir=new TMemoryStream();
Dir->LoadFromFile("c:\\windows");

Не по теме:


кстати точно так же через файловый стрим можно тома открывать. Например TFileStream("C:",faOpenRead); откроет на чтение том диска C: в RAW виде.

1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
26.08.2016, 16:54
Помогаю со студенческими работами здесь

Ускорить алгоритм удаления одного списка из другого
Здравствуйте. Есть два списка : один на 181093 строк другой на 80000. Нужно удалить один список из другого. Моя реализация: ...

Вывести итоговую строку с общим размером (в блоках) всех файлов в данной директории
Добрый день. Если в Linux в командной строке набрать команду &quot;ls -l&quot;, то перед каждым списком выводится итоговая строка с общим...

Получение списка файлов из директории
Кто-нибудь может подсказать как это делается на C(не ++). В исходниках ls найти не смог. Либо может кто-нибудь знает как получить вывод...

Вывод списка файлов из директории
Доброе время суток. Возникла проблема, мне необходимо осуществить вывод списка файлов из определенной директории(задается пользователем),...

Получение списка файлов в директории проекта
если запустить как java test.class * по получаем список файлов дтректории проэкта если /* - список файлов на диске public class...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru