DirectoryContainer: Руководство Программиста
DocumentId:GradSoft-PR-r-09.01.2001-v1.0.0
DirectoryContainer - это кроcсплатформенная компонета на C++,
предназначенная для навигации по списку имен файлов в директории.
Используя DirectoryIterator, Вы получаете простое
и, важно, одинаковое API для действий, связанных с просмотром директории
(таких как поиск файлов), для UNIX и для Windows NT.
Пакет DirectoryIterator разработан и поддерживается компанией GradSoft
и поставляется в исходных кодах.
Домашняя страница разработчика http://www.gradsoft.kiev.ua/
Этот документ является неформальным описанием пакета. Полная специфиткация
находится в описании API
(http://www.gradsoft.kiev.ua/common/ToolBox/DirectoryContainer/API/)
Реализованы два следующих подхода к порядку чтения директории:
- Объект DirectoryEntry позволяет работать с директорией традиционно как c потоком ввода;
- Объект DirectoryContainer позволяет работать с директорией как c STL-контейнером
для элементов DirectoryEntry.
Объект DirectoryEntry представляет собой позиционируемый объект
для работы с директорией как c потоком ввода.
Это значит что:
- Директория рассматриватся как последовательность элементов,
доступ к которым возможен через единственнный доступный указатель на "текущий" элемент;
DirectoryEntry рассматриватся как средство доступа к единственному
(текущему) элементу последовательности,
который, однако, можно сменить при помощи собственых средств DirectoryEntry.
- Для того, чтобы прочесть директорию, мы должны сначала ее "открыть",
а потом (вообще говоря) "закрыть".
В нашем случае директория открывается в момент создания объекта DirectoryEntry, поэтому,
для того, чтобы получить информацию о некотором элементе некоторой директории, мы должны:
- Создать объект DirectoryEntry для заданной директории и позиционировать его на заданном элементе;
- Вызвать метод, возвращающий информацию о текущем элементе последовательности.
try{
DirectoryEntry smth("."); // создать объект и позиционировать его
// на первом элементе последовательности
do {
cout<<smth.name()<<endl; // вывести имя текущего элемента
} while(smth.next()); // позиционировать объект на следующем
// элементе последовательности
} catch(DirectoryException& ex) { // см.ниже
cerr << ex.message << endl;
}
Данный код выводит имена файлов/поддиректорий, расположенных в текущей директории диска
Общие сведения:
Класс DirectoryEntry реализует модели Assignable и EqualityComparable,
т.е. имеет:
- Конструктор копирования и оператор "=";
- Операторы "==" и "!=".
В то же время класс не является DеfaultConstructable,
его стандартный конструктор объявлен приватным.
- Стандартные средства:
- DirectoryEntry(const DirectoryEntry& );
- DirectoryEntry& operator=(const DirectoryEntry& );
- bool operator==(const DirectoryEntry& ) const;
- bool operator!=(const DirectoryEntry& ) const;
- Средства управления потоком:
- Методы, возвращающие информацию о текущем элементе последовательности:
- const char* name() - возвращает имя текущего элемента (файла/поддиректории)
- int fsize() - возвращает размер файла либо 0, если текущий элемент является директорией
- bool is_directory() - возвращает true, если текущий элемент является директорией и false в противном случае
- bool is_hidden() - возвращает true, если текущий элемент является "скрытым"
(что может быть только под Windows) и false в противном случае
Внимание: если достигнут конец списка, значения, возвращаемые этими методами, не определены.
- Два объекта DirectoryEntry считаются равными, если они
- Не позиционированы (для каждого достигнут конец списка)
- позиционированы на одной и той же записи одной и той же директории,
причем идентификация записи производится по имени описываемого ею элемента.
DirectoryContainer представляет собой класс, который позволяет работать с директорией как c STL-контейнером
для элементов DirectoryEntry.
Объект DirectoryEntry при этом рассматривается исключительно как средство доступа
к одной-единственной записи директории,
позиционирование объекта DirectoryEntry его собственными средствами запрещено.
Сопряженный с контейнером итераторный тип реализован объектом DirectoryIterator 2.4
который представляет собой Forward Iterator для последоватеьности объектов DirectoryEntry
Пример:
DirectoryContainer dir(".");
DirectoryContainer::iterator it;
for( it=dir.begin(); it!=dir.end(); ++it ) cout << it->name() << endl;
Этот код делает то же, что и предыдущий,
с поправкой на то, что скобки try{ }catch здесь опущены.
- value_type - класс DirectoryEntry
- iterator - класс DirectoryIterator ()
- const_iterator - то же, что и iterator
- reference - ссылка на DirectoryEntry
- const_reference - константная ссылка на DirectoryEntry
- pointer - указатель на DirectoryEntry
- distance_type - тип, представляющий разницу между двумя экземплярами DirectoryIterator (long)
- size_type - long
- Стандартные средства:
- DirectoryContainer(DirectoryContainer&);
- DirectoryContainer& operator=(DirectoryContainer&);
- DirectoryIterator begin();
- static const DirectoryIterator& end();
- size_type size();
- size_type max_size();
- bool empty();
- void swap(DirectoryContainer&);
- Специальные средства:
- DirectoryContainer() - создает DirectoryContainer для текущей директории диска;
- DirectoryContainer(const char *path) - создает DirectoryContainer
для заданной директории диска;
Параметр: имя директории
- setPath(const char *path) - связывает DirectoryContainer
с заданной директорией диска;
Параметр: имя директории
- record_count() - возвращает количество записей в директории,
исключая ссылку на себя и ссылку на родительский каталог;
- bool no_records() - возвращает true, если директория не содержит
файлов/поддиректорий и false в противном случае.
Замечания:
- Метод size() возвращает общее количество записей в директории,
включая ссылку на себя и ссылку на родительский каталог.
В соответствии с этим, метод empty() почти всегда возвращает false
(исключение составляет проверка полностью пустого диска при работе под Windows).
Для того, чтобы узнать, не пуста ли директория в привычном смысле этого слова
(нет ли там файлов/поддиректорий), используйте метод no_files().
Класс DirectoryIterator
DirectoryIterator представляет собой служебный класс,
который является Forward-итератором для последовательности элементов DirectoryEntry.
Как Forward Iterator, он имеет следующие методы:
- DirectoryIterator(const DirectoryIterator& );
- DirectoryIterator& operator=(const DirectoryIterator& );
- DirectoryIterator& operator++();
- DirectoryIterator operator++(int);
- DirectoryEntry& operator*();
- const DirectoryEntry& operator*() const;
- DirectoryEntry* operator->();
- const DirectoryEntry* operator->() const;
- bool operator==(const DirectoryIterator& );
- bool operator!=(const DirectoryIterator& );
а также стандартный конструктор DirectoryIterator(),
который дает итератор, указывающий на виртуальный элемент "после последнего"
DirectoryException представляет собой исключение,
которое генерируется следующими методами класса DirectoryEntry:
- DirectoryEntry(const char* path);
~DirectoryEntry();
- DirectoryEntry(const DirectoryEntry& x);
- DirectoryEntry& operator=(const DirectoryEntry& x);
- bool next();
- bool find(const char* name);
- void close();
при ошибках системы, а также конструктором DirectoryEntry(cont *char) в том случае,
когда директория, имя которой передано в виде параметра, не существует.
Т.к. DirectoryIterator и DirectoryContainer являются надстройками над DirectoryEntry,
класс DirectoryException может быть послан следующими методами класса DirectoryIterator:
- DirectoryIterator(const DirectoryIterator& );
- operator=(const DirectoryIterator& );
- operator++();
- operator++(int);
а также следующими методами класса DirectoryContainer:
- begin()
- record_count()
- no_files()
- size()
- empty()
struct DirectoryException
{
long errno; // номер ошибки ОС
string message; // стандартное сообщение о системной ошибке
}
Данный пример демонстрирует порядок использования пакета DirectoryContainer:
#include <GradSoft/DirectoryContainer.h>
ifdef HAVE_NAMESPACES
#include <iostream>
using namespace std;
using namespace GradSoft;
#else
#include <iostream.h>
#endif
#include <stdio.h>
int main(int argc, char** argv)
if (argc!=2) {
cerr << "Usage: " << argv[0] << " path" << endl;
return 1;
}
cout<<endl<<">>>> 1 >>>>"<<endl;
// Usinig DirectoryEntry:
try{
DirectoryEntry smth(argv[1]);
do {
cout<<smth.name()<<endl;
} while(smth.next());
} catch(DirectoryContainer& ex) {
cerr << ex.message << endl;
}
cout<<endl<<">>>> 2 >>>>"<<endl;
// Using DirectoryContainer:
try{
DirectoryContainer dir(argv[1]);
Directory::iterator it;
for( it=dir.begin(); it!=dir.end(); ++it)
{
cout << it->name() ;
if ( it->is_directory() ) cout << " ( DIR ) ";
else cout << " ( " << it->fsize() << " ) ";
cout << endl;
}
} catch(const DirectoryException& ex) {
cerr << ex.message << endl;
}
return 0;
}
Если Вы работаете под управлением Windows NT, Вам необходимо:
- определить макрос WIN32 перед включением файла DirectoryContainer.h
- использовать "новые" библиотеки и, соответственно, заголовочные файлы iostream, fstream и т.п.
вместо аналогичных iostream.h, fstream.h и т.п.
- 16-10-2002
- исправлено несколько опечаток.
- 03-01-2002
- обновлен в соответствии с новой версией пакета 1.4.0
- 03-07-2001
- DirectoryIterator переименован в DirectoryContainer
- 16-05-2001
- Текст приведен в соответствие с изменениями в коде
- 09-01-2001
- Первая русская редакция.
- 15-01-2001
- FileIterator переименован в DirectoryIterator
GradSoft