Всем привет!
Есть папки с несколькими миллионами файлов внутри. Не спрашивайте почему или как, это пишет левая прога, которая не в наших руках.
Нужно показывать содержимое этих директориев.
Сейчас используем обычный Directory.GetFiles, который долго тупит на таком количестве файлов.
Наверняка мы не первые кто сталкивается с такой проблемой, но я по-быстрому не мог нагуглить решение.
В идеальном виде хотелось бы иметь что-то типа
Здравствуйте, HotDog, Вы писали:
HD>Сейчас используем обычный Directory.GetFiles, который долго тупит на таком количестве файлов.
.. HD>Может кто-то видел подобное решение?
Directory.EnumerateFiles ? По мере получения файлов можно складывать в спец. очередь, которую можно обрабатывать параллельно по мере поступления файлов.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>В нативном WinAPI есть ReadDirectoryChanges. Если нечто подобное есть в POSIX, то и в .NET, скорее всего, как-то отражено.
Да, есть — FileSystemWatcher (в win под капотом ReadDirectoryChanges).
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>В нативном WinAPI есть ReadDirectoryChanges. Если нечто подобное есть в POSIX, то и в .NET, скорее всего, как-то отражено.
Это немного не то. Это изменения в каталоге
А нужно FindFirstFile — FindNextFile
Или на .NET Directory.EnumerateFiles, как уже было отмечено.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А нужно FindFirstFile — FindNextFile
А, я-то подумал, что GetFiles вызывается регулярно, чтобы отслеживать появление новых файлов в каталоге. Если надо только один раз, то EnumerateFiles должно сгодиться.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>А, я-то подумал, что GetFiles вызывается регулярно, чтобы отслеживать появление новых файлов в каталоге. Если надо только один раз, то EnumerateFiles должно сгодиться.
Ну такие действия при миллионах файлов я бы вообще отказался делать
Но вообще-то EnumerateFiles это скорее всего настройка над FindFirstFile-FileNextFile. От GetFiles это будет отличаться тем, что не будет создан жуткого размера массив string[]. Все в одну переменную, как в FindFirstFile-FileNextFile. По крайней мере я на это надеюсь.
А вот в ядре асинхронно не будет. Это, если я правильно понимаю, можно только через NtQueryDirectoryFile c APC. Впрочем, тебе тут лучше знать
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>А надо? FindFileNext даже для миллионов файлов будет работать доли секунды.
Ох, не знаю. Миллионов файлов у меня не было, а вот примерно 100 тысяч в одном каталоге было, правда, лет 20 назад. И когда в FAR я входил в этот каталог, занимало это десятки секунд.
Конечно, не SDD, а HDD, да и 20 лет назад все же. Но те же 7200RPM.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Десятки секунд занимает обход всего каталога. А отдельная операция типа FindNextFile выполняется быстро.
Да, но ТС нужно именно весь. Да еще и не один каталог.
TC>Есть папки с несколькими миллионами файлов внутри. Не спрашивайте почему или как, это пишет левая прога, которая не в наших руках. TC>Нужно показывать содержимое этих директориев.
Здравствуйте, HotDog, Вы писали:
HD>Есть папки с несколькими миллионами файлов внутри. Не спрашивайте почему или как, это пишет левая прога, которая не в наших руках. HD>Нужно показывать содержимое этих директориев.
Я бы немного с другой стороны подошел бы.
Где показывать ? Сколько в окне показывать (не миллион же!). И как показывать — последовательно или в произвольном порядке, то есть с произвольным скроллингом ?
Если последовательно, то можно использовать для ListView или DataGridView виртуальный режим.
Начинаешь Directory.EnumerateFiles в отдельном потоке, заносишь данные в какой-то ArrayList с большой начальной емкостью (чтобы избежать насколько можно переаллокаций) и сразу же показываешь то, что поместилось в окне. Пока пользователь листает вперед, ArrayList дозаполняется.
Увы, если надо показывать в произвольном порядке, это не пройдет — там лишь IEnumerable.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>ТС спрашивал, можно ли это делать асинхронно (скорее всего, чтоб крутить индикатор ожидания). Он не просил чуда.
ЕМ>Десятки секунд занимает обход всего каталога. А отдельная операция типа FindNextFile выполняется быстро.
Это весьма сильное допущение. Устройство, на котором расположена ФС, может вести себя непредсказуемо.
Это может быть сетевой диск (SMB), iSCSI, WebDAV на канале с неизвестной пропускной способностью.
И подвисший UI, либо утекшие ресурсы из-за криво сделанного cancellation потом о себе дадут знать.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Где показывать ? Сколько в окне показывать (не миллион же!). И как показывать — последовательно или в произвольном порядке, то есть с произвольным скроллингом ?
По сути, у меня что то вроде эксплорера. Есть дерево каталогов (директориев) и пользователь просто клацает по директориям и хочет посмотреть что в них лежит. Понятно, что я не показываю все миллионы файлов за раз, но нужна быстрая реакция при выборе директория и возможность прервать загрузку. А сейчас это выглядит так — пользователь кликает на директорий и приложение "задумывается" на очень долго, т.к пока Directory.GetFiles все не вычитает, нам показывать нечего
PD>Начинаешь Directory.EnumerateFiles в отдельном потоке, заносишь данные в какой-то ArrayList с большой начальной емкостью (чтобы избежать насколько можно переаллокаций) и сразу же показываешь то, что поместилось в окне. Пока пользователь листает вперед, ArrayList дозаполняется. PD>Увы, если надо показывать в произвольном порядке, это не пройдет — там лишь IEnumerable.