mirror of
https://github.com/boostorg/filesystem.git
synced 2026-01-30 20:02:10 +00:00
288 lines
15 KiB
HTML
288 lines
15 KiB
HTML
<html>
|
|
|
|
<head>
|
|
<meta http-equiv="Content-Language" content="en-us">
|
|
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
|
<meta name="ProgId" content="FrontPage.Editor.Document">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
|
<title>Boost Filesystem Library</title>
|
|
</head>
|
|
|
|
<body bgcolor="#FFFFFF">
|
|
|
|
<h1>
|
|
<img border="0" src="../../../c++boost.gif" align="center" width="277" height="86">Boost
|
|
Filesystem Library</h1>
|
|
<table border="0" cellpadding="0" width="100%">
|
|
<tr>
|
|
<td width="50%" valign="top"><font size="4">This Document</font><br>
|
|
<a href="#Introduction">Introduction</a><br>
|
|
<a href="#tutorial">Two-minute tutorial</a><br>
|
|
<a href="#Examples">Examples</a><br>
|
|
|
|
<a href="#Definitions">Definitions</a><br>
|
|
|
|
<a href="#Requirements">Requirements</a><br>
|
|
<a href="#Race-condition">Race-condition danger</a><br>
|
|
<a href="#Acknowledgements">Acknowledgements</a></td>
|
|
<td width="50%"><font size="4">Other Documents</font><br>
|
|
<a href="design.htm">Library Design</a><br>
|
|
<a href="faq.htm">FAQ</a><br>
|
|
<a href="portability_guide.htm">Portability Guide</a><br>
|
|
<a href="path.htm"><b><i>path.hpp</i></b> documentation</a><br>
|
|
<a href="operations.htm"><b><i>operations.hpp</i></b> documentation</a><br>
|
|
<a href="fstream.htm"><b><i>fstream.hpp</i></b> documentation</a><br>
|
|
<a href="exception.htm"><b><i>exception.hpp</i></b> documentation</a><br>
|
|
<a href="do-list.htm">Do-list</a></td>
|
|
</tr>
|
|
</table>
|
|
<h2><a name="Introduction">Introduction</a></h2>
|
|
<p>The Boost Filesystem Library provides portable facilities to query and
|
|
manipulate paths, files, and directories.</p>
|
|
|
|
<p>The motivation for the library is the need to be able to perform portable script-like operations from within C++ programs. The intent is not to
|
|
compete with Python, Perl, or shell languages, but rather to provide portable filesystem
|
|
operations when C++ is already the language of choice. The <a href="design.htm">
|
|
design</a> encourages, but does not require, safe and portable filesystem usage.</p>
|
|
|
|
<p>Filesystem Library components are supplied by several headers, all in
|
|
directory boost/filesystem:</p>
|
|
|
|
<ul>
|
|
<li>Header <i>path.hpp</i> provides class <i>path, </i>a portable mechanism for representing
|
|
<a href="#path">paths</a> in C++ programs. Validity checking
|
|
functions are also provided. See <a href="path.htm">path.hpp documentation</a>.<br>
|
|
</li>
|
|
<li>Header <i>operations.hpp</i> provides functions operating on files and directories,
|
|
and includes class <i>directory_iterator</i>. See <a href="operations.htm">
|
|
operations.hpp documentation</a>.<br>
|
|
</li>
|
|
<li>Header <i>fstream.hpp</i> provides the same components as the C++ Standard
|
|
Library's <i>fstream</i> header, except
|
|
that files are identified by <i>path</i> objects rather that <i>char *</i>'s.
|
|
See <a href="fstream.htm">fstream.hpp documentation</a>.<br>
|
|
</li>
|
|
<li>Header <i>exception.hpp</i> provides class <i>filesystem_error</i>. See
|
|
<a href="exception.htm">exception.hpp documentation</a>.<br>
|
|
</li>
|
|
<li>Experimental header <i>
|
|
<a href="../../../boost/filesystem/recursive_directory_iterator.hpp">
|
|
recursive_directory_iterator.hpp</a></i> provides an undocumented directory
|
|
iterator which recurses into any sub-directories encountered. It will be
|
|
incorporated into the Filesystem Library if user feedback is favorable.</li>
|
|
</ul>
|
|
<h2>Two-minute <a name="tutorial">tutorial</a></h2>
|
|
<p>First some preliminaries:</p>
|
|
<blockquote>
|
|
<pre>#include "boost/filesystem/operations.hpp" // includes boost/filesystem/path.hpp
|
|
#include "boost/filesystem/fstream.hpp" // ditto
|
|
#include <iostream> // for cout
|
|
namespace fs = boost::filesystem;</pre>
|
|
</blockquote>
|
|
<p>A <a href="path.htm#synopsis">class <i>path</i></a> object can be created:</p>
|
|
<blockquote>
|
|
<pre>fs::path my_path( "some_dir/file.txt" );</pre>
|
|
</blockquote>
|
|
<p>The string passed to the <i>path</i> constructor is in a
|
|
<a href="path.htm#Grammar">portable generic path format</a>. Access functions
|
|
make <i>my_path</i> contents available in an operating system dependent format,
|
|
such as <code>"some_dir:file.txt"</code>, <code>"[some_dir]file.txt"</code>,
|
|
<code>"some_dir/file.txt"</code>, or whatever is appropriate for the
|
|
operating system.</p>
|
|
<p>Class <i>path</i> has conversion constructors from <i>const char*</i> and <i>
|
|
const std:: string&</i>, so that even though the Filesystem Library functions in
|
|
the following code snippet take <i>const path&</i> arguments, the user can just
|
|
code C-style strings:</p>
|
|
<blockquote>
|
|
<pre>fs::remove_all( "foobar" );
|
|
fs::create_directory( "foobar" );
|
|
fs::ofstream file( "foobar/cheeze" );
|
|
file << "tastes good!\n";
|
|
file.close();
|
|
if ( !fs::exists( "foobar/cheeze" ) )
|
|
std::cout << "Something is rotten in foobar\n";</pre>
|
|
</blockquote>
|
|
<p>Additional class path constructors provide for an operating system dependent
|
|
format, useful for with user provided input:</p>
|
|
<blockquote>
|
|
<pre>int main( int argc, char * argv[] ) {
|
|
fs::path arg_path( argv[1], fs::system_specific );</pre>
|
|
</blockquote>
|
|
<p>To make class <i>path</i> objects easy to use in expressions, <i>operator<<</i>
|
|
appends paths:</p>
|
|
<blockquote>
|
|
<pre>fs::ifstream file1( arg_path << "foo/bar" );
|
|
fs::ifstream file2( arg_path << "foo" << "bar" );</pre>
|
|
</blockquote>
|
|
<p>Note that expressions <i>arg_path << "foo/bar"</i> and <i>arg_path << "foo"
|
|
<< "bar"</i> yield equivalent results.</p>
|
|
<p><a href="operations.htm#Class directory_iterator">Class <i>directory_iterator</i></a>
|
|
is an important component of the library. It provides input iterators over the
|
|
contents of a directory, with the value type being class <i>path</i>.</p>
|
|
<p>The following function, given a directory path and a file name, recursively
|
|
searches the directory and its sub-directories for the file name, returning a
|
|
bool, and if successful, the path to the file that was found. The code
|
|
below is extracted from a real program, slightly modified for clarity:</p>
|
|
<blockquote>
|
|
<pre>bool find_file( const fs::path & dir_path, // in this directory,
|
|
const std::string & file_name, // search for this name,
|
|
fs::path & path_found ) // placing path here if found
|
|
{
|
|
if ( !fs::exists( dir_path ) ) return false;
|
|
fs::directory_iterator end_itr; // default construction yields past-the-end
|
|
for ( fs::directory_iterator itr( dir_path );
|
|
itr != end_itr;
|
|
++itr )
|
|
{
|
|
if ( fs::is_directory( *itr ) )
|
|
{
|
|
if ( find_file( *itr, file_name, path_found ) ) return true;
|
|
}
|
|
else if ( itr->leaf() == file_name ) // see below
|
|
{
|
|
path_found = *itr;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}</pre>
|
|
</blockquote>
|
|
<p>The expression <i>itr->leaf() == file_name</i>, in the line commented <i>//
|
|
see below</i>, calls the <i>leaf()</i> function on the <i>path</i> object
|
|
returned by the iterator. <i>leaf()</i> returns a string which is a copy of the
|
|
last (closest to the leaf, farthest from the root) file or directory name in the
|
|
<i>path</i> object.</p>
|
|
<p>Notice that <i>find_file()</i> does not do explicit error checking, such as
|
|
verifying that the <i>dir_path</i> argument really represents a directory. All
|
|
Filesystem Library functions throw <a href="exception.htm">filesystem_error</a>
|
|
exceptions if they do not complete successfully, so there is enough implicit
|
|
error checking that this application doesn't need to include additional error
|
|
checking code.</p>
|
|
<p>The tutorial is now over; hopefully you now are ready to write simple,
|
|
script-like, programs using the Filesystem Library!</p>
|
|
<h2><a name="Examples">Examples</a></h2>
|
|
<p>Until a custom-made example is available, see
|
|
<a href="../example/compiler_status.cpp">compiler_status.cpp</a>, an actual
|
|
program which uses the library.</p>
|
|
<p>Test programs are also sometimes useful in understanding a library, as they
|
|
illustrate what the developer expected to work and not work. See:</p>
|
|
<ul>
|
|
<li><a href="../test/path_test.cpp">path_test.cpp</a></li>
|
|
<li><a href="../test/operations_test.cpp">operations_test.cpp</a></li>
|
|
<li><a href="../test/fstream_test.cpp">fstream_test.cpp</a></li>
|
|
</ul>
|
|
<h2><a name="Definitions">Definitions</a></h2>
|
|
<p><b><a name="directory">directory</a> </b>- A container provided by the operating system,
|
|
containing the names of files, other directories, or both. Directories are identified
|
|
by <a href="#directory path">directory path</a>.</p>
|
|
<p><b><a name="directory tree">directory tree</a></b> - A directory and file
|
|
hierarchy viewed as an acyclic graph.</p>
|
|
<p><b><a name="path">path</a> </b>- A possibly empty sequence of names. Each
|
|
element in the sequence, except the last, names a <a href="#directory">directory</a>
|
|
which contains the
|
|
next element. The last element may name either a directory or file. The first
|
|
element is closest to the root of the directory tree, the last element is
|
|
farthest from the root.</p>
|
|
<p>It is traditional to represent a path as a string, where each element in the
|
|
path is represented by a <a href="#name">name</a>, and some operating system
|
|
defined syntax distinguishes between the name elements. Other representations of
|
|
a path are possible, such as each name being an element in a <code>std::vector<std::string></code>.</p>
|
|
<p><b><a name="file path">file path</a></b> - A <a href="#path">path</a> whose
|
|
last element is a file.</p>
|
|
<p><b><a name="directory path">directory path</a></b> - A <a href="#path">path</a>
|
|
whose last element is a directory.</p>
|
|
<p><b><a name="name">name</a></b> - A file or directory name, without any
|
|
<a href="#directory path">directory path</a> information to indicate the file or
|
|
directory's actual location within a directory tree. For some
|
|
operating systems, files and directories may have more than one valid name, such
|
|
as a short-form name and a long-form name.</p>
|
|
<h2><a name="Requirements">Requirements</a></h2>
|
|
<p>Unless otherwise specified, all Filesystem Library functions are required to
|
|
throw a <i><a href="exception.htm">filesystem_error</a></i> exception if the
|
|
implementation cannot successfully complete operations required to meet the
|
|
function's specifications. Such exceptions are in addition to any exceptions
|
|
specified in the function's "Throws" paragraph.</p>
|
|
<p>Filesystem Library functions are permitted to call C++ Standard Library
|
|
functions, so <i>std::bad_alloc</i> exceptions may also be thrown, unless
|
|
otherwise specified.</p>
|
|
<p>There is no rollback guarantee; a Filesystem Library function which throws an
|
|
exception may leave the external file system in an altered state.</p>
|
|
<h2><a name="Race-condition">Race-condition</a> d<a name="Dangers">anger</a></h2>
|
|
<p>The state of files and directories is often
|
|
globally shared, and thus may be changed unexpectedly by other threads,
|
|
processes, or even other computers which have access to the filesystem. As an
|
|
example of the difficulties this can cause, consider that the following asserts
|
|
may fail:</p>
|
|
<blockquote>
|
|
<p><code>assert( exists( "foo" ) == exists( "foo" ) ); //
|
|
(1)<br>
|
|
<br>
|
|
remove_all( "foo" );<br>
|
|
assert( !exists( "foo" ) ); // (2)<br>
|
|
<br>
|
|
assert( is_directory( "foo" ) == is_directory( "foo" ) ); //
|
|
(3)</code></p>
|
|
</blockquote>
|
|
<p>(1) will fail if a non-existent "foo" comes into existence, or an
|
|
existent "foo" is removed, between the first and second call to <i>exists()</i>.
|
|
This could happen if, during the execution of the example code, another thread,
|
|
process, or computer is also performing operations in the same directory.</p>
|
|
<p>(2) will fail if between the call to <i>remove_all()</i> and the call to
|
|
<i>exists()</i> a new file or directory named "foo" is created by another
|
|
thread, process, or computer.</p>
|
|
<p>(3) will fail if another thread, process, or computer removes an
|
|
existing file "foo" and then creates a directory named "foo", between the
|
|
example code's two calls to <i>is_directory()</i>.</p>
|
|
<p>A program which needs to be robust when operating on potentially-shared file
|
|
or directory resources should be prepared for <i>filesystem_error</i> exceptions
|
|
to be thrown from any filesystem function except those explicitly specified as
|
|
not throwing exceptions.</p>
|
|
<h2><a name="Implementation">Implementation</a></h2>
|
|
<p>The current implementation (September, 2002) supports operating systems that have
|
|
either the POSIX or Windows API's available.</p>
|
|
<p>The following tests are provided:</p>
|
|
<ul>
|
|
<li><a href="../test/path_test.cpp">path_test.cpp</a></li>
|
|
<li><a href="../test/operations_test.cpp">operations_test.cpp</a></li>
|
|
<li><a href="../test/fstream_test.cpp">fstream_test.cpp</a></li>
|
|
</ul>
|
|
<p>As of September, 2002, these tests succeed for the following compilers on Windows:</p>
|
|
<ul>
|
|
<li>Borland 5.5.1</li>
|
|
<li>GCC 3.1 (using POSIX implementation, but excluding wide-character fstream tests)</li>
|
|
<li>Intel 6.0</li>
|
|
<li>Metrowerks 8.2</li>
|
|
<li>Microsoft 7.0</li>
|
|
<li>Microsoft 6.0 except fstream_test failed.</li>
|
|
</ul>
|
|
<p>As of September, 2002, some limited use has been successful on Linux using
|
|
GCC and IBM/AIX using Visual Age C++.</p>
|
|
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
|
|
<p>The Filesystem Library was designed and implemented by Beman Dawes, except
|
|
for the <i>directory_iterator</i> and <i>filesystem_error</i> classes which were
|
|
based on prior work from Dietmar Kühl, as modified by Jan Langer.</p>
|
|
|
|
<p>Key <a href="design.htm#Requirements">design requirements</a> and
|
|
<a href="design.htm#Realities">design realities</a> were developed during extensive discussions on the Boost mailing list,
|
|
followed by comments on the actual implementation. Participants included
|
|
(in more-or-less chronological order) Beman Dawes, Jan Langer, Darin Adler, Michiel
|
|
Salters, Jani Kajala, Jason Stewart, Carl Daniel, David Abrahams, Bill Kempf,
|
|
Jonathan Caves, George Heintzelman, Ken Hagen, Eric Jensen, Joel de Guzman, Jim
|
|
Hyslop, John Maddock, Matt Austern, Peter Dimov, Davlet Panech, Dylan Nicholson, Tom Harris,
|
|
Giovanni Bajo, Baptiste Lepilleur, Thomas Witt, Keith Burton, Mattias Flodin,
|
|
Daniel Frey, Vladimir Prus, Toon Knapen.</p>
|
|
|
|
<p>Specific improvements for a preliminary design document came from Dan Nuffer and Jeff
|
|
Garland.</p>
|
|
|
|
<p>A lengthy discussion on the C++ committee's library reflector illuminated the "illusion
|
|
of portability" problem, particularly in postings by JP Plauger and Pete Becker.</p>
|
|
|
|
<hr>
|
|
<p>© Copyright Beman Dawes, 2002</p>
|
|
<p>Revised
|
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
|
|
|
|
</body>
|
|
|
|
</html> |