У цьому уроці ми з вами ознайомимося з основними принципами програмної організації пошуку файлів. Для початку визначимося, навіщо нам це може бути потрібно. Наприклад, вам потрібно при запуску програми на виконання просканувати певний каталог на присутність DOC файлів, і при наявності таких відкрити їх на редагування або надрукувати. А як вам така ідея: фоновий пошук EXE файлу в мережі, і при виявленні нової версії, автоматичне оновлення.
Багатьом відомі програми, де можна шукати файли, правила пошуку файлу. Файли можна шукати як з файлових командирів (нортон, вовків, дос навігатор, фар), так в будь-якій операційній системі. В операційній системі windows діалогове вікно пошуку файлу викликається "Пуск" - "Пошук" - "Файли і папки". У вікні, необхідно задати умову шуканого файлу (назва, маска) і шлях початкового пошуку (каталог). На інших вкладках цього діалогового вікна можна розширити можливості пошуку за датою зміни, по вмісту тексту, за розміром.
Згадаймо правила пошуку файлів. Ви можете задати як ім'я шуканого файлу, так і його маску, якщо назва невідомо чи необхідно знайти кілька. Тобто застосовуючи спеціальний шаблон пошуку, ви можете організувати умови вибірки знайдених файлів. Відразу обмовлюся, що пошук можна застосовувати як до файлів, так і до каталогів. Будемо їх називати елементами файлової системи. У шаблон маски шуканих елементів може входити:
- Букви і цифри в назві і розширенні.
- Символ * (зірочка, математичний знак "помножити"), який замінює будь-яку кількість всіляких букв і цифр у назві або розширенні.
- Символ. (Знак питання), який замінює одну букву або цифру в назві або розширенні шуканого елемента.
Наприклад, ви шукайте все текстові файли з розширенням TXT. В поле імені шуканого файлу вам потрібно ввести "* .TXT" (пишеться без лапок) і система знайде всі такі файли в зазначеному диску або каталозі. Якщо вам треба знайти всі файли з назвою semen, то в поле пошуку файли наступним чином "semen. *". Якщо вам потрібно знайти елементи з третьою буквою k і з першою літерою t в розширенні, то вводите "?? k * .t *". Тут знак питання вказує на будь-який символ, третім символом по порядку йде буква k, далі назва файлу (каталогу) може складатися з будь-якої кількості букв і цифр, вказуємо зірочку. У розширенні перша буква t, далі слід будь-яке розширення.
Примітка: файли і каталоги в операційній системі windows шукаються без урахування регістру, тобто малих і великих літер не розрізняються.
Тепер розглянемо програмний пошук файлів за допомогою мови програмування object pascal.
Вся організація циклу пошуку, а саме це і є цикл з продовженням пошуку, зводиться до:
- Завдання умов пошуку. Це каталог і маска шуканого елемента або елементів, атрибути елемента (ів). При завданні умов пошуку відразу відбувається пошук першого підходящого під умову. Це функція FindFirst.
- Продовження пошуку наступного елемента по заданих в першому пункті умов. Це функція FindNext і вона може бути викликана скільки завгодно раз, поки всі файли і каталоги, що задовольняють умові, що не будуть знайдені.
- Закриття пошуку і звільнення пам'яті, що виділяється системою під пошук. Команда FindClose.
Функція FindFirst.
де: Каталог для пошуку і маска шуканого елемента - строкова величина, що має тип String, може, наприклад, містити 'c: \ *. *' - все елементи в корені диска С. Зверніть увагу, що вказується повний шлях для пошуку.
Атрибути шуканого елемента це призначені для користувача або системні атрибути, які може мати файл (каталог, мітка диска). Ось їх перелік:
- faReadOnly - Файли "тільки читання". Такий атрибут встановлюється на файли, які не рекомендовано змінювати, видаляти. Такий атрибут мають файли, наприклад, записані на компакт-дисках.
- faHidden - Приховані файли. При звичайних установках браузера та командира ці файли невидимі.
- faSysFile - Системні файли.
- faVolumeID - Файл мітки диска. Такий елемент в своєму імені має назву диска (максимум 11 символів).
- faDirectory - Атрибут ознаки каталогу.
- faArchive - Звичайний файл. За замовчуванням встановлюється на заново створюваних файлах.
- faAnyFile - Якщо встановити в якості атрибута шуканих елементів, то буде проведений пошук по усім вищесказаним атрибутам.
Ці вам потрібно шукати тільки елементи, що мають атрибут "каталог" і "прихований", то можна застосувати знак математичного складання, наприклад faDirectory + faHidden.
Пошукова змінна має тип TSearchRec. У неї, при успішному результаті пошуку, буде занесено всі необхідні дані про знайдений файловому елементі.
Оскільки FindFirst є функцією, то вона повинна сама повертати деяке значення. Це значення має тип Integer і означає результат пошуку файлу (код помилки пошуку). Якщо файл знайдений, то приймає нульове значення.
Функція FindNext.
Ця операція продовжують пошук, заданий в функції FindNext. Повертає значення результату пошуку (нульове в разі успішного пошуку).
Процедура FindClose.
Закриває пошук і звільняє пам'ять, виділену системою під пошук.
Тепер розглянемо приклад. Припустимо, нам треба знайти всі файли і каталоги в каталозі DELPHI, що знаходиться на диску C. Надалі, ви можете самостійно, змінюючи маску, міняти умови пошуку. Для форми з компонентом ListBox1 і кнопкою Button1 реакція на OnClick по кнопці:
Представлений приклад коду, в принципі, є основою для організації більш поглибленого пошуку, пошуку файлів за часом створення, за що містяться словами. Якщо ви запустите цю програму на виконання, то при натисканні на кнопку Button1 ви побачите в списку в першій і другій рядку елементи "." і "..". Це елементи, які мають атрибут "каталог". Перший містить зв'язок з кореневим каталогом диска, другий містить зв'язок до каталогом верхнього рівня. З другим ви зустрічаєтеся в дискових командних оболонках, наприклад нортон, коли вибираєте каталог ".." і натискаєте на "введення". Тим самим ви потрапляєте в каталог на рівень вище. Природно, в нашій пошуковій програмі такі елементи не треба вносити в список, тому ми ігноруємо їх знаходження. Виправляємо процедуру натискання на кнопку Button1:
В цьому випадку, при знаходженні каталогу з ім'ям "." або з ім'ям ".." програма продовжить обробку циклу пошуку без виведення знайденого імені елемента в компонент списку ListBox1.
Тепер розглянемо тип TSearchRec. Він має в собі кілька корисних властивостей:
- Name - назва знайденого каталогу (файлу);
- Size - розмір файлу в байтах;
- Attr - атрибути каталогу (файлу);
- Time - упаковане значення часу і дати створення каталогу (файлу).
Всі перераховані вище властивості ми вже розглянули або вони зрозумілі відразу, за винятком властивості Time. Воно має тип Integer і містить в собі упаковане значення дати і часу створення файлу. Розпакування проводиться за допомогою функції FileDateToDateTime, яка в результаті повертає значення дати і часу.
Тепер додамо в нашу форму компонент DateTimePicher1 (сторінка Win32) і допишемо кілька рядків.
Як ви вже помітили, ми відбираємо файли і каталоги за датою створення, починаючи з зазначеної в компоненті DateTimePicker1.
Тепер спробуємо організувати пошук файлів у всіх вкладених каталогах. Це не так просто, як може здатися на перший погляд. Нам доведеться вручну організовувати весь цикл входу-виходу з каталогу, перебір файлів. Трохи важкувато матеріал, але можливо ті з вас, хто вже працював з мовою програмування pascal або іншим, знайомі з технологією многократности і многовложенності використання одного і того ж програмного коду. Коротко поясню алгоритм роботи такої програми.
- Завдання початкових умов пошуку, пошук першого елемента.
- Якщо знайдений файл, то виводимо його і відповідно обробляємо (виводимо в список, відкриваємо, видаляємо і т.п.).
- Якщо знайдений каталог, то починаємо нову процедуру пошуку. Але програмний код залишається тим самим. Ми просто заново викликаємо і входимо в цю ж процедуру пошуку.
- Обробляємо таким же чином всі вкладені в цей каталог файли і каталоги (починаємо новий пошук в знайденому каталозі).
- Якщо елементів у вкладеному каталозі більше немає, то обробка процедури пошуку в ньому завершується, і ми виходимо з неї. При цьому ми опиняємося в тому ж місці, звідки і викликали цю процедуру. Але вона була викликана з цієї ж процедури. Тому програма продовжує своє виконання далі з моменту повернення.
Таким чином, скільки витків програма намотує на так званий клубок, стільки витків вона і розмотати. Програма на виконанні проходить все дерево вкладених каталогів, виконуючи один і той же шматок програмного коду! І при цьому дані умовам пошуку не переплутуються, і для кожної унікальної процедури вони зберігаються.
Розглянемо приклад. Створіть новий проект. Для створення окремої процедури пошуку нам потрібно оголосити її у відповідному розділі (створюємо її вручну, тому й самостійно оголошуємо).
У розділі public пишемо рядок:
А в розділі коду програми, до слова "end." вставляємо порожній каркас процедури
На форму вставляємо компонент списку ListBox1, Button1, Edit1. Для компонента Edit1 властивість Text встановлюємо в "c: \ delphi". Зверніть увагу на останній символ, знак "", присутність якого в початковому шляху пошуку обов'язково. Далі процедура OnClick для кнопки Button1 виглядає наступним чином:
Створена нами вручну процедура пошуку:
Якщо ви в компоненті Edit1 в якості початкового умови пошуку файлів задасте кореневу папку диска, наприклад "З:", то ви отримаєте повний перелік всіх файлів на даному диску. Зверніть увагу на швидкість пошуку файлів і швидкість роботи вашої програми.
procedure // назву процедури;
assignfile (f,); // прив'язуємо файл до змінної
Reset (f); // відкриваємо його для читання
readln (f, s); // зчитуємо один рядок. При кожному наступному виклику процедури читається наступний рядок
if EOF (f) then Break; // якщо кінець файлу, то виходимо з циклу
// далі обробляємо цей рядок як вам потрібно
Until // тут для отмази вставляємо яке-небудь умова завершення циклу, яке проте не повинно виконатися до закінчення перевірки файлу
Працює тільки для текстових файлів будь-якого розширення. Для обробки не текстових файлів (doc, html, і т.д.) потрібен інший алгоритм (ніколи цими файлами не займався, не знаю)