Boost C++ Filesystem Library - библиотека для работы с именами файлов

Данный документ
    Вступление
    Двух-минутный курс обучения
    Примеры
    Определения
    Общие спецификации
    Опасность race-condition
    Реализация
    Благодарности
    История изменений
Другие документы
    Дизайн библиотеки
    ЧАВО
    Руководство по портабельности
    Документация к path.hpp
    Документация к operations.hpp
    Документация к fstream.hpp
    Документация к exception.hpp
    Документация к convenience.hpp
    Планы

Вступление

Библиотека Boost.Filesystem предоставляет портабельные средства для работы с файловыми путями (далее - пути), файлами и каталогами.

Необходимость создания данной библиотеки заключается в том, чтобы иметь средства выполнения операций с путями в стиле скриптовых языков на C++. В намерения не входит состязание с языками Python, Perl, или командными языками ОС, а просто дать возможность использовать портабельные операции с файловой системой в случаях, когда язык C++ уже выбран. Дизайн библиотеки поощряет, хотя и не требует, безопасного и платформонезависимого использования файловой системы.

Библиотека Boost.Filesystem включает несколько хидеров, располагающихся в каталоге boost/filesystem:

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

Файлы исходных текстов (convenience.cpp, exception.cpp, operations_posix_windows.cpp, и path_posix_windows.cpp) находятся в каталоге libs/filesystem/src. Эти исходные тексты содержат реализацию библиотеки Boost.Filesystem для ОС POSIX и Windows; для других операционных систем реализации нет. Обратите внимание, что многие ОС, не являющиеся нормальными POSIX или Windows системами, такие как ОС мэйнфреймов или ОС встроенные систем, содержат поддержку совместимых с POSIX файловых систем, которые будут нормально работать с библиотекой Boost.Filesystem.

Объектная библиотека может быть построена для статического или динамического связывания. Это контролируется макросами BOOST_ALL_DYN_LINK и BOOST_FILESYSTEM_DYN_LINK. См. страничку Раздельная компиляция с описанием использованного приема.

Объектные библиотеки могут быть построены с помощью файла Jamfile, находящегося в каталоге libs/filesystem/build.

Двухминутный курс обучения

Подготовка к работе:

#include "boost/filesystem/operations.hpp" // includes boost/filesystem/path.hpp
#include "boost/filesystem/fstream.hpp"    // ditto
#include <iostream>                        // for std::cout
using boost::filesystem;                   // for ease of tutorial presentation;
                                           // a namespace alias is preferred in real code

Теперь можно создавать объект класса path:

path my_path( "some_dir/file.txt" );

Передаваемая в конструктор path строка должна иметь портабельный общий формат пути. Функции доступаделают содержимое my_path доступным в родном для используемой ОС формате, таком как "some_dir:file.txt", "[some_dir]file.txt", "some_dir/file.txt", или другом, принятом для конкретной ОС.

Класс path имеет конструкторы преобразования из const char* и const std:: string&, в следующем коде с применением функций Boost.Filesystem, получающих аргументы типа const path&, можно применять си-строки:

remove_all( "foobar" );
create_directory( "foobar" );
ofstream file( "foobar/cheeze" );
file << "tastes good!\n";
file.close();
if ( !exists( "foobar/cheeze" ) )
  std::cout << "Something is rotten in foobar\n";

Дополнительные конструкторы класса path предназначены для использования с форматом путей, специфичном для используемой ОС:

int main( int argc, char * argv[] ) {
path arg_path( argv[1], native ); // native означает использование формата путей ОС

Чтобы упростить использование объектов класса path в выражениях, с помощью operator/ можно выполнять объединение путей:

ifstream file1( arg_path / "foo/bar" );
ifstream file2( arg_path / "foo" / "bar" );

Выражения  arg_path / "foo/bar" и arg_path / "foo" / "bar" дают идентичные результаты.

Пути могут включать ссылки на родительский каталог, используя обозначение "..". пути всегда автоматически конвертируются в каноническую форму, так что "foo/../bar" конвертируется в "bar", а "../foo/../bar" преобразуется в "../bar".

Класс directory_iterator это важный компонент библиотеки. Он предоставляет входной итератор над содержимым каталога, тип value определен как класс path.

Следующая функция, для заданных пути к каталогу и имени файла, рекурсивно обходит каталог и его подкаталоги в поисках заданного имени, возвращая true, если поиск успешен, и путь к найденному файлу. Код извлечен из реальной программы, и слегка модифицирован для ясности:

bool find_file( const path & dir_path,     // в этом каталоге,
                const std::string & file_name, // искать такое имя,
                path & path_found )        // разместить путь здесь если удалось найти
{
  if ( !exists( dir_path ) ) return false;
  directory_iterator end_itr; // default construction yields past-the-end
  for ( directory_iterator itr( dir_path );
        itr != end_itr;
        ++itr )
  {
    if ( is_directory( *itr ) )
    {
      if ( find_file( *itr, file_name, path_found ) ) return true;
    }
    else if ( itr->leaf() == file_name ) // см. далее
    {
      path_found = *itr;
      return true;
    }
  }
  return false;
}

Выражение itr->leaf() == file_name, в строке с комментарием  // см. далее, вызывает функцию leaf() для объекта path, возвращенного итератором. leaf() возвращает строку, которая являетмя копией последнего  (ближайшего к концу, самого дальнего от корня) имени файла или каталога в объекте path.

В дополнение к leaf(), несколько других функций используют метафору дерева/корня/верки/листа.

Обратите внимание, что find_file() не делает явной проверки ошибок, к примеру проверки, что аргумент dir_path действительно указывает на каталог. Все ошибки библиотеки Boost.Filesystem  генерируют исключение filesystem_error, если они не завершаются успешно, так что достаточно неявной проверки на ошибки и данная программа не нуждается в дополнительном проверочном коде.

Учебный курс теперь закончен, теперь Вы пожалуй можете писать простые, в стиле скриптов, программы, используя библиотеку Boost.Filesystem!

Примеры

simple_ls.cpp

Демонстрационная программа simple_ls.cpp получает путь как аргумент командной строки. Так как аргумент командной строки может быть относительным путем, то программа определяет полный путь, и отображаемые сообщения дают более точную информацию о путях.

Программа проверяет, что заданный путь существует, если нет - отображается сообщение.

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

Если заданный путь соответствует файлу, то печатается сообщение.

Попробуйте откомпилировать и выполнить simple_ls.cpp, чтобы увидеть, как программа работает на вашей системе. Попробуйте задавать различные начальные пути и посмотреть, что случится.

Примечание: поисковый движок FAIND, точнее входящий в его состав паук, использует практически буквально такой же код для просмотра дерева каталоговв.

Другие примеры

Эти программы используются для генерации таблиц состояния регрессионного теста Boost. Они широко используют средства библиотеки Boost.Filesystem:

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

Определения

каталог - контейнер, управляемый операционной системой, содержащий имена файлов и вложенных каталогов. Каталоги идентифицируются путями_каталогов.

дерево_каталогов - иерархия каталогов и файлов, представляемая в виде ациклического графа. Метафора дерева отражена в соглашении об названиях корень/ветка/лист для многих функций, связанных с обработкой путей.

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

Традиционно путь представляется как строка, где каждый элемент пути представлен именем, и некоторые операционные системы определяют, как синтаксически отделяются элементы. Возможны другие представления пути, к примеру в виде контейнера std::vector<std::string>, хранящего отдельные имена.

файловый путь - это путь, последний элемент которого является файлом.

путь к каталогу - это путь, последний элемент которого является каталогом.

полный путь - это путь, который содержит все элементы, необходимые операционной системе для уникальной идентификации файла или каталога. (Есть пограничные случаи, когда полный путь может все же быть неоднозначным на некоторых платформах).

относительный путь - это путь, который не является полным. Перед реальным использованием относительный путь преобразуется в полный путь, либо неявно службой файловой системы, либо явно в программе, с помощью добавления пропущенных элементов. Использование относительных путей часто делает программы более гибкими.

имя - имя файла или каталога, без пути к каталогу, который указывает на действительное расположение в дереве каталогов. Для некоторых операционных систем файлы и каталоги могут иметь больее чем одно корректное имя, к примеру - краткая форма имени (имена 8.3 - наследиеMS DOS) и полная форма.

корень - начальный узел ациклического графа, который представляет дерево каталогов файловой системы.

многокорневая операционная система - ОС, в которой могут быть несколько корней. Некоторый ОС имеют отдельные деревья каталогов для каждого диска, устройства, тома, и других сущностей, управляемых системой, с корнем для каждого дерева.

линк (ссылка) - имя в каталоге может рассматриваться как указатель на другой каталог или файл. Современные операционные системы допускают ситуацию, когда несколько элементов каталогов указывают на один и тот же каталог или файл. Такой указатель часто называется линком (ссылкой). Не все операционные системы имеют поддержку концепции линков. Линки могут с подсчетом числа ссылок  (жесткие линки) или без подсчета числа ссылок (символические линки).

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

символический линк - это линк без подсчета числа ссылок. Операционная система управляет некоторыми аспектами символического линка. Большинство операций, такие как открытие файла, автоматически выполняются с указываемым файлом, а не с файлом линка. Некоторые операции, такие как remove() и rename(), модифицируют символический линк, а не указываемый им файл или каталог. См. важное предупреждение по поводу символических ссылок.

Общие спецификации

Если не указано другое, все функции Boost.Filesystem, включая методы классов, имеют следующую общую спецификацию:

Соблюдение послеусловий не гарантируется в условиях race-conditions - спецификации функций Boost.Filesystem следуют спецификациям стандартной библиотеки C++, и поэтому в ряде случаев определяют поведение в терминах послеусловий. При наличии race-condition, послеусловия функции могут более не соблюдаться к моменту возврата из функции.

Могут генерировать исключения - функции библиотеки Boost.st.Filesystem могут генерировать исключение filesystem_error, если они не могут успешно завершить заданную для них работу. Реализации функций могут использовать функции стандартной библиотеки C++, которые могут сгенерировать std::bad_alloc. Эти исключения могут быть сгенерированы даже в случае, если условия, приведшие к генерации исключения, не заданы явно в секции "Throws" в описании соответствующей функции.

Исключения генерируются посредством boost::throw_exception() - все исключения, генерируемые функциями библиотеки Boost.Filesystem, бросаются посредством вызова boost::throw_exception(). Таким образом точное поведение может различаться в зависимости от определения макроса BOOST_NO_EXCEPTIONS в момент компиляции исходных файлов библиотеки Boost.Filesystem.

Линки подчиняются правилам операционной системы - линки прозрачны для функций библиотеки Boost.st.Filesystem, так как их обработка оставлена за ОС. Это подразумевает, что некоторые функции могут сгенерировать искючение filesystem_error, если линк зациклен или имеет другие проблемы. Также следует учитывать предупреждение по поводу символических ссылок.

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

Обоснование: соответствует существующей практике (POSIX, Windows, и т.д.).

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

Обоснование: создатели реализаций библиотеки не должны быть обязаны давать гарантии, которые невозможно удовлетворить на некоторых ОС. Разработчики лишь поощряются для поддержки таких гарантий когда это возможно.

Допущение частичной реализации - те функции библиотеки Boost.Filesystem, которые не могут быть полностью реализованы на конкретной платформе, погут быть реализованы частично Разработчики должны документировать случаи такой частичной реализации. Функции, которые вызываются для выполнения операции, которую они не могут выполнить в силу своей ограниченности, должны в этом случае сгенерировать ошибку, предпочтительно на стадии компиляции, либо сгенерировать исключение во время работы программы.

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

Опасность race-condition

Файлы и каталоги зачастую могут непредсказуемо меняться из-за воздействий параллельных процессов, или даже из-за операций, выполняемых по локальной сети. В качестве примера возникающих трудностей обратите внимание, что следующие проверки могут оказаться некорректными:

assert( exists( "foo" ) == exists( "foo" ) );  // (1)

remove_all( "foo" );
assert( !exists( "foo" ) );  // (2)

assert( is_directory( "foo" ) == is_directory( "foo" ) ); // (3)

(1) не сработает, если не существующий "foo" появляется, или существующий "foo" удаляется, между первым и вторым вызовом exists(). Это может случиться если во время выполнения кода другой процесс или компьютер также выполняют операции в том же каталоге.

(2) не сработает, если между вызовом remove_all() и вызовом exists() другой процесс или компьютер создадут файл или каталок с именем "foo".

(3) не сработает, если другой процесс или компьютер удалят существующий файл "foo" и затем создадут каталог с тем же именем между двумя вызовами is_directory().

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

Реализация

Текущая реализация поддерживает операционные системы, для которых есть POSIX или Windows API.

Предоставляются следующие тесты:

Библиотека постоянно используется на Apple Mac OS, HP-UX, IBM AIX, Linux, Microsoft Windows, SGI IRIX, и Sun Solaris с разными компиляторами.

Благодарности

Библиотека Boost.Filesystem была спроектирована и реализована Биманом Доусом (Beman Dawes). Классы directory_iterator и filesystem_error основаны на первоначальной разработке Дитмара Кюля (Dietmar Kühl) и модифицированы Жаном Ланже (Jan Langer). Томас Уит (Thomas Witt) оказал некоторую помощь на поздних стадиях разработки.

Ключевые требования к дизайну и реальности дизайна были разработаны в процессе длительных дискуссий в почтовой рассылке Boost, за которыми последовали комментарии к первым реализациям. Большое количество полезных комментариев было затем получено в процессе пересмотра формата (Formal Review).

Participants included Aaron Brashears, Alan Bellingham, Aleksey Gurtovoy, Alex Rosenberg, Alisdair Meredith, Andy Glew, Anthony Williams, Baptiste Lepilleur, Beman Dawes, Bill Kempf, Bill Seymour, Carl Daniel, Chris Little, Chuck Allison, Craig Henderson, Dan Nuffer, Dan'l Miller, Daniel Frey, Darin Adler, David Abrahams, David Held, Davlet Panech, Dietmar Kuehl, Douglas Gregor, Dylan Nicholson, Ed Brey, Eric Jensen, Eric Woodruff, Fedder Skovgaard, Gary Powell, Gennaro Prota, Geoff Leyland, George Heintzelman, Giovanni Bajo, Glen Knowles, Hillel Sims, Howard Hinnant, Jaap Suter, James Dennett, Jan Langer, Jani Kajala, Jason Stewart, Jeff Garland, Jens Maurer, Jesse Jones, Jim Hyslop, Joel de Guzman, Joel Young, John Levon, John Maddock, John Williston, Jonathan Caves, Jonathan Biggar, Jurko, Justus Schwartz, Keith Burton, Ken Hagen, Kostya Altukhov, Mark Rodgers, Martin Schuerch, Matt Austern, Matthias Troyer, Mattias Flodin, Michiel Salters, Mickael Pointier, Misha Bergal, Neal Becker, Noel Yap, Parksie, Patrick Hartling, Pavel Vozenilek, Pete Becker, Peter Dimov, Rainer Deyke, Rene Rivera, Rob Lievaart, Rob Stewart, Ron Garcia, Ross Smith, Sashan, Steve Robbins, Thomas Witt, Tom Harris, Toon Knapen, Victor Wagner, Vincent Finn, Vladimir Prus, and Yitzhak Sapir

A lengthy discussion on the C++ committee's library reflector illuminated the "illusion of portability" problem, particularly in postings by PJ Plauger and Pete Becker.

Walter Landry provided much help illuminating symbolic link use cases for version 1.32.0.

История изменений

Version 1.32.0


Revised 09 июня, 2005

© Copyright Beman Dawes, 2002

Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at www.boost.org/LICENSE_1_0.txt)

последняя правка: 26.05.2005

библиотека BOOST C++ http://www.boost.org
перевод Elijah Koziev www.solarix.ru

  © Mental Computing 2010