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

MS-DOS для программиста

© Александр Фролов, Григорий Фролов
Том 19, М.: Диалог-МИФИ, 1995, 253 стр.

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

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

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

Это функции 4Eh и 4Fh.

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

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

Затем для поиска остальных файлов, удовлетворяющих заданному ранее образцу, в цикле вызывается функция 4Fh. Условие завершения цикла - отсутствие в каталоге указанных файлов.

Функция 4Eh вызывается следующим образом:

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

Функция 4Fh имеет следующие параметры вызова:

На входе: AH 4Fh
На выходе: AL Код ошибки, если был установлен флаг переноса 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.

Стандартная библиотека Borland C++ содержат две функции, предназначенные для сканирования каталогов. Это _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];     // имя файла и расширение
};

Программа DIRLIST

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


Листинг 3.3. Файл dirlist\dirlist.cpp


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

void print_info(struct find_t *find);
char *time_conv(unsigned time, char *char_buf);
char *date_conv(unsigned date, char *char_buf);

#pragma argsused
int 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("Задайте образец для поиска файлов !");
    return(-1);
  }

  // Выводим информацию об остальных найденных файлах
  while(!_dos_findnext (&find)) print_info( &find );
  return(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, 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;
}

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