Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Операционная система MS-DOS

© Александр Фролов, Григорий Фролов
Том 1, книга 3, М.: Диалог-МИФИ, 1992.

[Назад] [Содеожание] [Дальше]

3.3. Поиск в каталогах

Часто перед программистом стоит задача определения текущего содержимого каталога. При описании логической структуры диска мы приводили текст программы, выводящей на экран содержимого корневого каталога и других каталогов. Эта программа использовала загрузочный сектор логического диска и таблицу размещения файлов. Вы можете использовать такой способ, однако, если вам не требуется информация о номерах начальных кластеров файлов и дескрипторы удаленных файлов, лучше применить специальные функции MS-DOS, предназначенные для поиска файлов в каталогах.

Пара функций 4Eh и 4Fh предназначены для сканирования каталогов.

Эти функции используются вместе следующим образом:

  • Вызывается функция 4Eh для поиска в каталоге файла, соответствующего образцу. В образце можно использовать символы ? и *, которые означают, соответственно, один любой символ и любое количество любых символов. Информация о найденном файле располагается в специальной области, назначенной каждой работающей программе - области DTA.
  • Вызывается в цикле функция 4Fh для поиска остальных файлов, удовлетворяющих образцу, заданному при вызове функции 4Eh. Условие завершения цикла - отсутствие в каталоге указанных файлов.

Приведем формат вызова функций 4Eh и 4Fh.

Функция 4Eh:

На входе: AH = 4Eh
CX = Атрибуты файла, которые будут использованы при поиске. Будут найдены файлы, имеющие заданный в этом регистре атрибут.
DS:DX = Адрес строки в формате ASCIIZ, содержащей путь каталогаили файла.
На выходе: AL = Код ошибки, если был установлен в 1 флаг переноса CF.

Функция 4Fh:

На входе: AH = 4Fh
На выходе: AL = Код ошибки, если был установлен в 1 флаг переноса CF.

Обе функции устанавливают флаг переноса в том случае, когда каталог не содержит файлов, удовлетворяющих заданному критерию поиска.

Для работы с областью DTA MS-DOS имеет две функции. Это функция 2Fh, позволяющая получить адрес области DTA (она возвращает этот адрес в регистрах ES:BX), и функция 1Ah, предназначенная для установки своей области DTA (адрес новой области DTA должен быть указан в регистрах DS:DX).

Напомним, что по умолчанию область DTA занимает 128 байтов в префиксе сегмента программы PSP со смещением 80h.

В случае успешного поиска функции 4Eh и 4Fh помещают в DTA информацию о найденных файлах в следующем формате:

(0) 20 Зарезервировано.
(+21) 1 Атрибуты найденного файла
(+22) 2 Поле времени последнего обновления фалйла
(+24) 2 Поле даты последнего обновления фалйла
(+26) 4 Длина файла
(+30) 13 Имя файла и расширение в формате ASCIIZ

Номер начального класетра, распределенного файлу или каталогу, невозможно получить с помощью функций 4Eh и 4Fh.

Стандартные библиотеки трансляторов Microsoft QC 2.5 и C 6.0 содержат две функции, предназначенные для сканирования каталогов - _dos_findfirst() и _dos_findnext().

Приведем прототипы этих функций, описанные в файле dos.h:

int _dos_findfirst(char *pattern, struct find_t *found,
                                unsigned attr);
int _dos_findnext(struct find_t *found);

В этих функциях параметр pattern определяет образец для поиска файлов, параметр attr - атрибуты файла - используется в качестве дополнительного критерия поиска. Параметр found представляет собой указатель на структуру, в которую будет записываться информация о найденных файлах. Эта структура определена в файле dos.h:

struct find_t {
        char reserved[21];      // Зарезервировано для DOS
        char attrib;            // Атрибуты файла
        unsigned wr_time;       // Время изменения файла
        unsigned wr_date;       // Дата изменения файла
        long size;              // Размер файла в байтах
        char name[13];          // Имя файла и расширение
};

Приведем текст программы просмотра содержимого каталога. Программа принимает из командной строки параметр - образец для показа файлов. Если вы укажете параметр *.*, будет выведена информация обо всех файлах. Можно задавать полный путь: c:\*.*.

#include <stdlib.h>
#include <stdio.h>
#include <dos.h>

void main(int argc, char *argv[]) ;
void print_info(struct find_t *find);
char *time_conv(unsigned time, char *char_buf);
char *date_conv(unsigned date, char *char_buf);

void main(int argc, char *argv[]) {

         struct find_t find;

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

         if(!_dos_findfirst(argv[1], 0xffff, &find)) {

                  printf("\n"
                         "\nИмя файла    Аттр. Дата        Время     Размер"
                         "\n------------ ----- ----------  --------  ------");

// Выводим информацию о первом найденном файле на экран

                  print_info(&find);
         }
         else {
                  printf("Задайте образец для поиска файлов !");
                  exit(-1);
         }

// Выводим информацию об остальных найденных файлах

         while(!_dos_findnext(&find)) print_info( &find );

         exit(0);
}

// Функция для вывода информации о найденных файлах

void print_info(struct find_t *pfind) {

         char timebuf[10], datebuf[12];

// Преобразуем формат даты и времени последнего изменения файла

         date_conv(pfind->wr_date, datebuf);
         time_conv(pfind->wr_time, timebuf);

// Выводим содержимое дескриптора файла

                printf("\n%-12s",pfind->name);
                printf(" %02X    %8s  %8s %8ld ",
                        pfind->attrib,
                        datebuf,
                        timebuf,
                        pfind->size);
}

// Функция преобразования формата времени

char *time_conv(unsigned t, char *buf) {

         int h, m;

         h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f;
         sprintf(buf, "%2.2d:%02.2d:%02.2d", h % 12, m, (t & 0x1f) * 2);
         return buf;
}

// Функция преобразования формата даты

char *date_conv(unsigned d, char *buf) {

         sprintf(buf, "%2.2d.%02.2d.%04.2d",
                                 d & 0x1f,(d >> 5) & 0x0f, (d >> 9) + 1980);
         return buf;
}

При запуске программы с параметром *.com на экран будет выведена информация:

Имя файла    Аттр. Дата        Время     Размер
------------ ----- ----------  --------  ------
CURDIR.COM   20    24.02.1991  08:40:24     5879 
DIRCTL.COM   20    24.02.1991  09:10:30     6273 
DISK_CTL.COM 20    13.01.1991  03:26:34     8177 
DISKA.COM    20    19.01.1991  10:08:58       27 
DISKB.COM    20    04.02.1991  08:57:34     6186 
DISKINFO.COM 20    24.02.1991  04:08:42     6075 
DISKSHOW.COM 20    31.01.1991  09:48:34     6989 
PARTSHOW.COM 20    07.02.1991  06:12:02     7357 
DIRM.COM     20    26.02.1991  11:59:50     6346 
[Назад] [Содеожание] [Дальше]