Книга: Системное программирование в среде Windows

Пример: вывод списка атрибутов файла

Пример: вывод списка атрибутов файла

Настало время увидеть функции управления файлами и каталогами в действии. Программа 3.2 представляет собой ограниченную версию команды UNIX ls, предназначенной для вывода содержимого каталогов, которая позволяет вывести дату и время последнего изменения файла и размер файла, хотя данная версия отображает лишь младшую часть размера файла.

Программа просматривает каталог для поиска файлов, соответствующих шаблону поиска. Для каждого найденного файла программа отображает имя файла и, если был задан параметр –1, то и его атрибуты. Данная программа иллюстрирует принцип построения многих, хотя и далеко не всех, функций Windows, предназначенных для работы с каталогами. 

Значительная часть кода программы 3.2 отвечает за обход дерева каталогов. Заметьте, что каждый каталог проходится дважды: при первом проходе обрабатываются файлы, а при втором — подкаталоги, чем обеспечивается поддержка параметра рекурсивного обхода каталогов (-R).

В том виде, как она представлена ниже, программа 3.2 будет корректно выполняться в том случае, если при ее вызове используются относительные полные имена файлов, например:

lsW –R include*.h

Вместе с тем, в результате указания абсолютного полного имени файла, например:

lsW –R C:ProjectslsDebug*.obj

правильная работа программы будет нарушена, поскольку в ней самым существенным образом используется привязка каталогов к текущему каталогу. Завершенное решение (доступное на Web-сайте) анализирует абсолютные полные пути доступа к файлам и поэтому обеспечивает правильное выполнение программы и для второй команды.

Программа 3.2. lsw: вывод списка файлов и обход дерева каталогов 

/* Глава 3. lsW — команда вывода списка файлов */
/* lsW [параметры] [файлы] */
#include "EvryThng.h"
BOOL TraverseDirectory(LPCTSTR, DWORD, LPBOOL);
DWORD FileType(LPWIN32_FIND_DATA);
BOOL ProcessItem(LPWIN32_FIND_DATA, DWORD, LPBOOL);
int _tmain(int argc, LPTSTR argv[]) {
 BOOL Flags [MAX_OPTIONS], ok = TRUE;
 TCHAR PathName [MAX_PATH +1], CurrPath [MAX_PATH + 1];
 LPTSTR pSlash, pFileName;
 int i, FileIndex;
 FileIndex = Options(argc, argv, _T("R1"), &Flags[0], &Flags[1], NULL);
 I* "Разобрать" шаблон поиска на "родительскую часть" и имя файла. */
 GetCurrentDirectory(MAX_PATH, CurrPath); /* Сохранить текущий путь доступа. */
 if (argc < FileIndex +1) /* Путь доступа не указан. Использовать текущий каталог. */
  ok = TraverseDirectory(_T("*"), MAX_OPTIONS, Flags);
 else for (i = FileIndex; i < argc; i++) {
  /* Обработать все пути, указанные в командной строке. */
  ok = TraverseDirectory(pFileName, MAX_OPTIONS, Flags) && ok;
  SetCurrentDirectory(CurrPath);
  /* Восстановить каталог. */
 }
 return ok ? 0 : 1;
}
static BOOL TraverseDirectory(LPCTSTR PathName, DWORD NumFlags, LPBOOL Flags)
/* Обход дерева каталогов; выполнить функцию ProcessItem для каждого случая совпадения. */
/* PathName: относительное или абсолютное имя просматриваемого каталога.*/
{
 HANDLE SearchHandle;
 WIN32_FIND_DATA FindData;
 BOOL Recursive = Flags[0];
 DWORD FType, iPass;
 TCHAR CurrPath[MAX_PATH + 1];
 GetCurrentDirectory(MAX_PATH, CurrPath);
 for (iPass = 1; iPass <= 2; iPass++) {
  /* Проход 1: вывод списка файлов. */
  /* Проход 2: обход дерева каталогов (если задана опция –R). */
  SearchHandle = FindFirstFile(PathName, &FindData);
  do {
   FType = FileType(&FindData);
   /* Файл или каталог? */
   if (iPass == 1) /* Вывести имя и атрибуты файла. */
    ProcessItem(&FindData, MAX_OPTIONS, Flags);
   if (FType == TYPE_DIR && iPass == 2 && Recursive) {
    /* Обработать подкаталог. */
    _tprintf(_T ("n%s%s:"), CurrPath, FindData.cFileName);
    /* Подготовка к обходу каталога. */
    SetCurrentDirectory(FindData.cFileName);
    TraverseDirectory(_T("*"), NumFlags, Flags);
    /* Рекурсивный вызов. */
    SetCurrentDirectory(_T(".."));
   }
  } while (FindNextFile(SearchHandle, &FindData));
  FindClose (SearchHandle);
 }
 return TRUE;
}
static BOOL ProcessItem(LPWIN32_FIND_DATA pFileData, DWORD NumFlags, LPBOOL Flags)
/* Выводит список атрибутов файла или каталога. */
{
 const TCHAR FileTypeChar[] = {' ', 'd'};
 DWORD FType = FileType(pFileData);
 BOOL Long = Flags[1];
 SYSTEMTIME LastWrite;
 if (FType != TYPE_FILE && FType != TYPE_DIR) return FALSE;
 _tprintf(_T ("n"));
 if (Long) { /* Указан ли в командной строке параметр "-1"? */
  _tprintf(_T("%c"), FileTypeChar[FType – 1]);
  _tprintf(_T("%10d"), pFileData->nFileSizeLow); 
  FileTimeToSystemTime(&(pFileData->ftLastWriteTime), &LastWrite);
  _tprintf(_T(" %02d/%02d/%04d %02d:%02d:%02d"), LastWrite.wMonth, LastWrite.wDay, LastWrite.wYear, LastWrite.wHour, LastWrite.wMinute, LastWrite.wSecond);
 }
 _tprintf(_T(" %s"), pFileData->cFileName);
 return TRUE;
}
static DWORD FileType(LPWIN32_FIND_DATA pFileData)
/* Поддерживаемые типы файлов – TYPE_FILE: файл; TYPE_DIR: каталог; TYPE_DOT: каталоги . или .. */
{
 BOOL IsDir;
 DWORD FType;
 FType = TYPE_FILE;
 IsDir = (pFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
 if (IsDir) if (lstrcmp(pFileData->cFileName, _T(".")) == 0 || lstrcmp(pFileData->cFileName, _T("..")) == 0) FType = TYPE_DOT;
 else FType = TYPE_DIR;
 return FType;
}

Оглавление книги


Генерация: 1.108. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз