12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340 |
- <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=utf-8">
- <title>Filesystem Tutorial</title>
- <link href="styles.css" rel="stylesheet">
- </head>
- <body>
- <table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
- <tr>
- <td width="277">
- <a href="../../../index.htm">
- <img src="../../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="300" height="86" border="0"></a></td>
- <td align="middle">
- <font size="7">Filesystem Tutorial</font>
- </td>
- </tr>
- </table>
- <table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse"
- bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
- <tr>
- <td><a href="index.htm">Home</a>
- <a href="tutorial.html">Tutorial</a>
- <a href="reference.html">Reference</a>
- <a href="faq.htm">FAQ</a>
- <a href="release_history.html">Releases</a>
- <a href="portability_guide.htm">Portability</a>
- <a href="v3.html">V3 Intro</a>
- <a href="v3_design.html">V3 Design</a>
- <a href="deprecated.html">Deprecated</a>
- <a href="issue_reporting.html">Bug Reports </a>
- </td>
- </table>
- <p>
- <a href="#Introduction">Introduction</a><br>
- <a href="#Preliminaries">Preliminaries</a><br>
- <a href="#Reporting-size">Reporting the size of a file - (tut1.cpp)</a><br>
- <a href="#Using-status-queries">Using status queries to determine file existence and type - (tut2.cpp)</a><br>
- <a href="#Directory-iteration">Directory iteration plus catching
- exceptions - (tut3.cpp)</a><br>
- <a href="#Using-path-decomposition">Using path decomposition, plus sorting results - (tut4.cpp)</a><br>
- <a href="#Class-path-Constructors">Class path: Constructors, including
- Unicode - (tut5.cpp)</a><br>
- <a href="#Class-path-formats">Class path: Generic format vs. Native format</a><br>
- <a href="#Class path-iterators-etc">Class path: Iterators, observers, composition, decomposition, and query - (path_info.cpp)</a><br>
- <a href="#Error-reporting">Error reporting</a><br>
- </p>
- <h2><a name="Introduction">Introduction</a></h2>
- <p>This tutorial develops a little command line program to list information
- about files and directories - essentially a much simplified version of the POSIX <code>ls</code> or Windows <code>dir</code>
- commands. We'll start with the simplest possible version and progress to more
- complex functionality. Along the way we'll digress to cover topics you'll need
- to know about to understand Boost.Filesystem.</p>
- <p>Source code for each of the tutorial programs is available, and you
- are encouraged to compile, test, and experiment with it. To conserve space, we won't
- always show boilerplate code here, but the provided source is complete and
- ready to build.</p>
- <h2><a name="Preliminaries">Preliminaries</a></h2>
- <p>Install the Boost distribution if you haven't already done so. See the
- <a href="http://www.boost.org/more/getting_started/index.html">Boost Getting
- Started</a> docs.</p>
- <p>This tutorial assumes you are going to compile and test the examples using
- the provided scripts. That's highly recommended.</p>
- <blockquote>
- <p><b>If you are planning to compile and test the examples but not use the
- scripts, make sure your build setup knows where to
- locate or build the Boost library binaries.</b></p>
- </blockquote>
- <p>Fire up your command line interpreter, and type the following commands:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td>
- <pre>$ cd <i><b>boost-root</b></i>/libs/filesystem/example/test
- $ ./setup.sh
- Copying example programs...
- $ ./build.sh
- Compiling example programs...
- $ ./tut1
- Usage: tut1 path</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td>
- <pre>>cd <i><b>boost-root</b></i>\libs\filesystem\example\test
- >setup
- Copying example programs...
- >build
- Compiling example programs...
- >tut1
- Usage: tut1 path</pre>
- </td>
- </tr>
- </table>
- <p>If the <code>tut1</code> command outputs "<code>Usage: tut1 path</code>", all
- is well. A set of tutorial example programs has been copied (by <code>setup</code>) to
- <i><b><code>boost-root</code></b></i><code>/libs/filesystem/example/test</code>
- and then built. You are encouraged to modify and experiment with them as the
- tutorial progresses. Just invoke the <code>build</code> script again to rebuild,
- or invoke <code>b2</code> directly.</p>
- <p>If something didn't work right, here are some troubleshooting suggestions:</p>
- <ul>
- <li>If the <code>b2</code> program executable isn't being found, check your path environmental variable
- or see
- <a href="http://www.boost.org/more/getting_started/windows.html">Boost
- Getting Started</a>.<br>
- </li>
- <li>Look at <code>b2.log</code> to try to spot an indication of the
- problem.</li>
- </ul>
- <h2><a name="Reporting-size">Reporting the size of a file</a> - (<a href="../example/tut1.cpp">tut1.cpp</a>)</h2>
- <p>Let's get started. Our first example program, <a href="../example/tut1.cpp">tut1.cpp</a>,
- reports the size of a file:</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/tut1.cpp" -->#include <iostream>
- #include <boost/filesystem.hpp>
- using namespace boost::filesystem;
- int main(int argc, char* argv[])
- {
- if (argc < 2)
- {
- std::cout << "Usage: tut1 path\n";
- return 1;
- }
- std::cout << argv[1] << " " << file_size(argv[1]) << '\n';
- return 0;
- }<!-- end include file --></pre>
- </td>
- </tr>
- </table>
- <p>The Boost.Filesystem <code><a href="reference.html#file_size">file_size</a></code>
- function returns a <code>uintmax_t</code>
- containing the size of the file named by the argument. The declaration looks
- like this:</p>
- <blockquote>
- <pre><code>uintmax_t file_size(const path& p);</code> </pre>
- </blockquote>
- <p>For now, all you need to know is that <code>class path</code> has constructors that take
- <code>const char *</code> and other string types. (If you can't wait to
- find out more, skip ahead to the <a href="#Class-path-Constructors">class path</a> section of
- the tutorial.)</p>
- <p>Please take a minute to try out <code>tut1</code> on your system, using a
- file that is known to exist, such as <code>tut1.cpp</code>. Here is what the
- results look like on two different operating systems:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>$ ./tut1 tut1.cpp
- tut1.cpp 569</pre>
- <pre>$ ls -l tut1.cpp
- -rw-rw-r-- 1 beman beman 569 Jul 26 12:04 tut1.cpp</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>>tut1 tut1.cpp
- tut1.cpp 592
- >dir tut1.cpp
- ...
- 07/26/2015 07:20 AM 592 tut1.cpp
- ...</pre>
- </td>
- </tr>
- </table>
- <p>So far, so good. The reported Linux and Windows sizes are different because
- the Linux tests used <code>"\n"</code> line endings, while the Windows tests
- used <code>"\r\n"</code> line endings. The sizes reported may differ
- from the above if changes have been made to <code>tut1.cpp</code>.</p>
- <p>Now try again, but give a path that doesn't exist:</p>
- <table border="1" cellpadding="5" cellspacing="0"
- style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>$ ./tut1 foo
- terminate called after throwing an instance of 'boost::filesystem::filesystem_error'
- what(): boost::filesystem::file_size: No such file or directory: "foo"
- Aborted (core dumped)</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0"
- style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>>tut1 foo</pre>
- <p><b><i>An exception is thrown;<br>
- the exact form of the response depends on
- Windows system options.</i></b></td>
- </tr>
- </table>
- <p>What happens?
- There's no file named <code>foo</code> in the current directory, so by default an
- exception is thrown. See <a href="#Error-reporting">Error reporting</a> to learn
- about error reporting via error codes rather than exceptions.</p>
- <p>Try this:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td>
- <pre>$ ./tut1 .
- terminate called after throwing an instance of 'boost::filesystem::filesystem_error'
- what(): boost::filesystem::file_size: Operation not permitted: "."
- Aborted (core dumped)</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>>tut1 .</pre>
- <p><b><i>An exception is thrown;<br>
- the exact form of the response depends on Windows system options.</i></b></td>
- </tr>
- </table>
- <p>The current directory exists, but <code>file_size()</code> works on regular
- files, not directories, so again an exception is thrown.</p>
- <p>We'll deal with those situations in <code>tut2.cpp</code>.</p>
- <h2><a name="Using-status-queries">Using status queries to determine file existence and type</a> - (<a href="../example/tut2.cpp">tut2.cpp</a>)</h2>
- <p>Boost.Filesystem includes status query functions such as <code>
- <a href="reference.html#exists-path">exists</a></code>,
- <code><a href="reference.html#is_directory-path">is_directory</a></code>, and <code>
- <a href="reference.html#is_regular_file-path">is_regular_file</a></code>. These return
- <code>bool</code>'s, and will return <code>true</code> if the condition
- described by their name is met. Otherwise they return <code>false</code>,
- including when any element
- of the path argument can't be found.</p>
- <p><a href="../example/tut2.cpp">tut2.cpp</a> uses several of the status query functions to cope with non-existent
- files and with different kinds of files:</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/tut2.cpp" -->#include <iostream>
- #include <boost/filesystem.hpp>
- using namespace std;
- using namespace boost::filesystem;
- int main(int argc, char* argv[])
- {
- if (argc < 2)
- {
- cout << "Usage: tut2 path\n";
- return 1;
- }
- path p(argv[1]); // avoid repeated path construction below
- if (exists(p)) // does path p actually exist?
- {
- if (is_regular_file(p)) // is path p a regular file?
- cout << p << " size is " << file_size(p) << '\n';
- else if (is_directory(p)) // is path p a directory?
- cout << p << " is a directory\n";
- else
- cout << p << " exists, but is not a regular file or directory\n";
- }
- else
- cout << p << " does not exist\n";
- return 0;
- }<!-- end include file --></pre>
- </td>
- </tr>
- </table>
- <p>Give it a try:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>$ ./tut2 tut2.cpp
- "tut2.cpp" size is 997
- $ ./tut2 foo
- "foo" does not exist
- $ ./tut2 .
- "." is a directory</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>>tut2 tut2.cpp
- tut2.cpp size is 1039
- >tut2 foo
- "foo" does not exist
- >tut2 .
- "." is a directory</pre>
- </td>
- </tr>
- </table>
- <p>Although tut2 works OK in these tests, the output is less than satisfactory
- for a directory. We'd typically like to see a list of the directory's contents. In <code>tut3.cpp</code>
- we will see how to iterate over directories.</p>
- <p>But first, let's try one more test:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>$ ls /home/jane/foo
- ls: cannot access /home/jane/foo: No such file or directory
- $ ./tut2 /home/jane/foo
- terminate called after throwing an instance of 'boost::
- filesystem::filesystem_error>'
- what(): boost::filesystem::status: Permission denied:
- "/home/jane/foo"
- Aborted</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>>dir e:\
- The device is not ready.
- >tut2 e:\</pre>
- <p dir="ltr"><b><i>An exception is thrown;<br>
- the exact form of the response depends on
- Windows system options.</i></b></td>
- </tr>
- </table>
- <p>On the Linux system, the test was being run from an account that did not have
- permission to access <code>/home/jane/foo</code>. On the Windows system, <code>
- e:</code> was a Compact Disc reader/writer that was not ready. End users
- shouldn't have to interpret cryptic exceptions reports, so as we move on to <code>tut3.cpp</code>
- we will increase the robustness of the code, too.</p>
- <h2><a name="Directory-iteration">Directory iteration</a> plus catching
- exceptions - (<a href="../example/tut3.cpp">tut3.cpp</a>)</h2>
- <p>Boost.Filesystem's <code><a href="reference.html#directory_iterator">
- directory_iterator</a></code> class is just what we need here. It follows the
- general pattern of the standard library's <code>istream_iterator</code>. Constructed from
- a path, it iterates over the contents of the directory. A default constructed <code>directory_iterator</code>
- acts as the end iterator.</p>
- <p>The value type of <code>directory_iterator</code> is <code>
- <a href="reference.html#directory_entry">directory_entry</a></code>. A <code>
- directory_entry</code> object contains <code>path</code> and <code><a href="reference.html#file_status">file_status</a></code>
- information. A <code>
- directory_entry</code> object
- can be used directly, but can also be passed to <code>path</code> arguments in function calls.</p>
- <p>The other need is increased robustness in the face of the many kinds of
- errors that can affect file system operations. We could do that at the level of
- each call to a Boost.Filesystem function (see <a href="#Error-reporting">Error
- reporting</a>), but for simplicity <a href="../example/tut3.cpp">tut3.cpp</a>
- uses an overall try/catch block.</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/tut3.cpp" -->#include <iostream>
- #include <boost/filesystem.hpp>
- using std::cout;
- using namespace boost::filesystem;
- int main(int argc, char* argv[])
- {
- if (argc < 2)
- {
- cout << "Usage: tut3 path\n";
- return 1;
- }
- path p (argv[1]);
- try
- {
- if (exists(p))
- {
- if (is_regular_file(p))
- cout << p << " size is " << file_size(p) << '\n';
- else if (is_directory(p))
- {
- cout << p << " is a directory containing:\n";
- for (directory_entry& x : directory_iterator(p))
- cout << " " << x.path() << '\n';
- }
- else
- cout << p << " exists, but is not a regular file or directory\n";
- }
- else
- cout << p << " does not exist\n";
- }
- catch (const filesystem_error& ex)
- {
- cout << ex.what() << '\n';
- }
- return 0;
- }<!-- end include file --></pre>
- </td>
- </tr>
- </table>
- <p>Give <code>tut3</code> a try, passing it a path to a directory as a command line argument.
- Here is a run on a checkout of the Boost Git develop branch, followed by a repeat
- of the test cases that caused exceptions on Linux and Windows:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>$ ./tut3 ~/boost/develop
- "/home/beman/boost/develop" is a directory containing:
- "/home/beman/boost/develop/rst.css"
- "/home/beman/boost/develop/boost"
- "/home/beman/boost/develop/boost.png"
- "/home/beman/boost/develop/libs"
- "/home/beman/boost/develop/doc"
- "/home/beman/boost/develop/project-config.jam.2"
- "/home/beman/boost/develop/.gitmodules"
- "/home/beman/boost/develop/boostcpp.py"
- "/home/beman/boost/develop/.travis.yml"
- "/home/beman/boost/develop/.gitattributes"
- "/home/beman/boost/develop/index.htm"
- "/home/beman/boost/develop/index.html"
- "/home/beman/boost/develop/bjam"
- "/home/beman/boost/develop/project-config.jam.1"
- "/home/beman/boost/develop/LICENSE_1_0.txt"
- "/home/beman/boost/develop/.git"
- "/home/beman/boost/develop/tools"
- "/home/beman/boost/develop/stage"
- "/home/beman/boost/develop/boostcpp.jam"
- "/home/beman/boost/develop/Jamroot"
- "/home/beman/boost/develop/.gitignore"
- "/home/beman/boost/develop/INSTALL"
- "/home/beman/boost/develop/more"
- "/home/beman/boost/develop/bin.v2"
- "/home/beman/boost/develop/project-config.jam"
- "/home/beman/boost/develop/boost-build.jam"
- "/home/beman/boost/develop/bootstrap.bat"
- "/home/beman/boost/develop/bootstrap.sh"
- "/home/beman/boost/develop/status"
- "/home/beman/boost/develop/boost.css"</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>>tut3 \boost\develop
- "\boost\develop" is a directory containing:
- "\boost\develop\.git"
- "\boost\develop\.gitattributes"
- "\boost\develop\.gitignore"
- "\boost\develop\.gitmodules"
- "\boost\develop\.travis.yml"
- "\boost\develop\bin.v2"
- "\boost\develop\boost"
- "\boost\develop\boost-build.jam"
- "\boost\develop\boost.css"
- "\boost\develop\boost.png"
- "\boost\develop\boostcpp.jam"
- "\boost\develop\boostcpp.py"
- "\boost\develop\bootstrap.bat"
- "\boost\develop\bootstrap.sh"
- "\boost\develop\doc"
- "\boost\develop\index.htm"
- "\boost\develop\index.html"
- "\boost\develop\INSTALL"
- "\boost\develop\Jamroot"
- "\boost\develop\libs"
- "\boost\develop\LICENSE_1_0.txt"
- "\boost\develop\more"
- "\boost\develop\project-config.jam"
- "\boost\develop\rst.css"
- "\boost\develop\stage"
- "\boost\develop\status"
- "\boost\develop\tools"</pre>
- <pre>>tut3 e:\
- boost::filesystem::status: The device is not ready: "e:\"</pre>
- </td>
- </tr>
- </table>
- <p>Not bad, but we can make further improvements:</p>
- <ul>
- <li>The listing would be much easier to read if only the filename was
- displayed, rather than the full path.<br>
- </li>
- <li>The Linux listing isn't sorted. That's because the ordering of
- directory iteration is unspecified. Ordering depends on the underlying
- operating system API and file system specifics. So we need to sort the
- results ourselves. </li>
- </ul>
- <p>The next sections show how those changes play out, so read on!</p>
- <h2><a name="Using-path-decomposition">Using path decomposition, plus sorting results</a> - (<a href="../example/tut4.cpp">tut4.cpp</a>)</h2>
- <p>For directories, <a href="../example/tut4.cpp">tut4.cpp</a> builds a <code>
- std::vector</code> of all the entries and then sorts it before writing to <code>
- cout</code>.</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/tut4.cpp" -->#include <iostream>
- #include <vector>
- #include <algorithm>
- #include <boost/filesystem.hpp>
- using std::cout;
- using namespace boost::filesystem;
- int main(int argc, char* argv[])
- {
- if (argc < 2)
- {
- cout << "Usage: tut4 path\n";
- return 1;
- }
- path p (argv[1]);
- try
- {
- if (exists(p))
- {
- if (is_regular_file(p))
- cout << p << " size is " << file_size(p) << '\n';
- else if (is_directory(p))
- {
- cout << p << " is a directory containing:\n";
- std::vector<path> v;
- for (auto&& x : directory_iterator(p))
- v.push_back(x.path());
- std::sort(v.begin(), v.end());
- for (auto&& x : v)
- cout << " " << x.filename() << '\n';
- }
- else
- cout << p << " exists, but is not a regular file or directory\n";
- }
- else
- cout << p << " does not exist\n";
- }
- catch (const filesystem_error& ex)
- {
- cout << ex.what() << '\n';
- }
- return 0;
- }<!-- end include file --></pre>
- </blockquote>
- </td>
- </tr>
- </table>
- <p>The only difference between <code>tut3.cpp</code> and <code>tut4.cpp</code> is
- what happens for directories. We changed:</p>
- <blockquote>
- <pre>for (const directory_entry& x : directory_iterator(p))
- cout << " " << x.path() << '\n';</pre>
- </blockquote>
- <p>to:</p>
- <blockquote>
- <pre>std::vector<path> v;
- for (auto&& x : directory_iterator(p))
- v.push_back(x.path());
- std::sort(v.begin(), v.end());
- for (auto&& x : v)
- cout << " " << x.filename() << '\n';
- </pre>
- </blockquote>
- <p> <code>
- <a href="reference.html#path-filename">filename()</a></code> is one of
- several class <code>path</code> decomposition functions. It extracts the
- filename portion
- from a path (<font face="Courier New">i.e. </font><code>"index.html"</code><font face="Courier New">
- from </font><code>"/home/beman/boost/trunk/index.html"</code>). These decomposition functions are
- more fully explored in the <a href="#Class path-iterators-etc">Path iterators, observers,
- composition, decomposition and query</a> portion of this tutorial.</p>
- <p>The above was written as two lines of code for clarity. It could have
- been written more concisely as:</p>
- <blockquote>
- <pre>v.push_back(it->path().filename()); // we only care about the filename</pre>
- </blockquote>
- <p>Here is the output from a test of <code><a href="../example/tut4.cpp">tut4.cpp</a></code>:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td>
- <pre>$ ./tut4 v</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td>
- <pre>$ ./tut4 ~/boost/develop
- "/home/beman/boost/develop" is a directory containing:
- .git
- .gitattributes
- .gitignore
- .gitmodules
- .travis.yml
- INSTALL
- Jamroot
- LICENSE_1_0.txt
- bin.v2
- boost
- boost-build.jam
- boost.css
- boost.png
- boostcpp.jam
- boostcpp.py
- bootstrap.bat
- bootstrap.sh
- doc
- index.htm
- index.html
- libs
- more
- project-config.jam
- project-config.jam.1
- project-config.jam.2
- rst.css
- stage
- status
- tools</pre>
- </td>
- </tr>
- </table>
- <p>That completes the main portion of this tutorial. If you haven't already
- worked through the <a href="#Class-path-Constructors">Class path</a> sections of this tutorial, dig into them now.
- The <a href="#Error-reporting">Error reporting</a> section may also be of
- interest, although it can be skipped unless you are deeply concerned about
- error handling issues.</p>
- <h2><a name="Class-path-Constructors">Class path: Constructors</a>,
- including Unicode - (<a href="../example/tut5.cpp">tut5.cpp</a>)</h2>
- <p>Traditional C interfaces pass paths as <code>const char*</code> arguments.
- C++ interfaces may add <code>const std::string&</code> overloads, but adding
- overloads becomes untenable if wide characters, containers, and iterator ranges
- need to be supported.</p>
- <p>Passing paths as <code>const path&</code> arguments is far simpler, yet far
- more flexible because class <code>path</code> itself is far more flexible:</p>
- <ol>
- <li>Class <code>path</code> supports multiple character types and encodings, including Unicode, to
- ease internationalization.</li>
- <li>Class <code>path</code> supports multiple source types, such as iterators for null terminated
- sequences, iterator ranges, containers (including <code>std::basic_string</code>),
- and <code><a href="reference.html#Class-directory_entry">directory_entry</a></code>'s,
- so functions taking paths don't need to provide several overloads.</li>
- <li>Class <code>path</code> supports both native and generic pathname formats, so programs can be
- portable between operating systems yet use native formats where desirable.</li>
- <li>Class <code>path</code> supplies a full set of iterators, observers, composition,
- decomposition, and query functions, making pathname manipulations easy,
- convenient, reliable, and portable.</li>
- </ol>
- <p>Here is how (1) and (2) work. Class path constructors,
- assignments, and appends have member templates for sources. For example, here
- are the constructors that take sources:</p>
- <blockquote>
- <pre>template <class <a href="reference.html#Source">Source</a>>
- path(Source const& source);</pre>
- <pre>template <class InputIterator>
- path(InputIterator begin, InputIterator end);</pre>
- </blockquote>
- <p>Let's look at a little program that shows how comfortable class <code>path</code> is with
- both narrow and wide characters in C-style strings, C++ strings, and via C++
- iterators:</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/tut5.cpp" -->#include <boost/filesystem/fstream.hpp>
- #include <string>
- #include <list>
- namespace fs = boost::filesystem;
- int main()
- {
- // \u263A is "Unicode WHITE SMILING FACE = have a nice day!"
- std::string narrow_string ("smile2");
- std::wstring wide_string (L"smile2\u263A");
- std::list<char> narrow_list;
- narrow_list.push_back('s');
- narrow_list.push_back('m');
- narrow_list.push_back('i');
- narrow_list.push_back('l');
- narrow_list.push_back('e');
- narrow_list.push_back('3');
- std::list<wchar_t> wide_list;
- wide_list.push_back(L's');
- wide_list.push_back(L'm');
- wide_list.push_back(L'i');
- wide_list.push_back(L'l');
- wide_list.push_back(L'e');
- wide_list.push_back(L'3');
- wide_list.push_back(L'\u263A');
- { fs::ofstream f("smile"); }
- { fs::ofstream f(L"smile\u263A"); }
- { fs::ofstream f(narrow_string); }
- { fs::ofstream f(wide_string); }
- { fs::ofstream f(narrow_list); }
- { fs::ofstream f(wide_list); }
- narrow_list.pop_back();
- narrow_list.push_back('4');
- wide_list.pop_back();
- wide_list.pop_back();
- wide_list.push_back(L'4');
- wide_list.push_back(L'\u263A');
- { fs::ofstream f(fs::path(narrow_list.begin(), narrow_list.end())); }
- { fs::ofstream f(fs::path(wide_list.begin(), wide_list.end())); }
- return 0;
- }<!-- end include file --></pre>
- </td>
- </tr>
- </table>
- <p>Testing <code>tut5</code>:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>$ ./tut5
- $ ls smile*
- smile smile☺ smile2 smile2☺ smile3 smile3☺ smile4 smile4☺</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td valign="top">
- <pre>>tut5
- >dir /b smile*
- smile
- smile2
- smile2☺
- smile3
- smile3☺
- smile4
- smile4☺
- smile☺</pre>
- </td>
- </tr>
- </table>
- <p>The exact appearance of the smiling face will depend on the font,
- font size, and other settings for your command line window. The above tests were
- run with out-of-the-box Ubuntu 14.04 and Windows 7, US Edition. If you don't get
- the above results, take a look at the <code><i>boost-root</i>/libs/filesystem/example/test</code>
- directory with your system's GUI file browser, such as Linux Nautilus, Mac OS X
- Finder, or Windows Explorer. These tend to be more comfortable with
- international character sets than command line interpreters.</p>
- <p>Class <code>path</code> takes care of whatever character type or encoding
- conversions are required by the particular operating system. Thus as <code>
- tut5</code> demonstrates, it's no problem to pass a wide character string to a
- Boost.Filesystem operational function even if the underlying operating system
- uses narrow characters, and visa versa. And the same applies to user supplied
- functions that take <code>const path&</code> arguments.</p>
- <p>Class <code>path</code> also provides path syntax that is portable across operating systems,
- element iterators, and observer, composition, decomposition, and query
- functions to manipulate the elements of a path. The next section of this
- tutorial deals with path syntax.</p>
- <h2><a name="Class-path-formats">Class path: Generic format vs. Native format</a></h2>
- <p>Class <code>path</code> deals with two different pathname
- formats - generic format and native format. For POSIX-like
- file systems, these formats are the same. But for users of Windows and
- other non-POSIX file systems, the distinction is important. Even
- programmers writing for POSIX-like systems need to understand the distinction if
- they want their code to be portable to non-POSIX systems.</p>
- <p>The <b>generic format</b> is the familiar <code>/my_directory/my_file.txt</code> format used by POSIX-like
- operating systems such as the Unix variants, Linux, and Mac OS X. Windows also
- recognizes the generic format, and it is the basis for the familiar Internet URL
- format. The directory
- separator character is always one or more slash characters.</p>
- <p>The <b>native format</b> is the format as defined by the particular
- operating system. For Windows, either the slash or the backslash can be used as
- the directory separator character, so <code>/my_directory\my_file.txt</code>
- would work fine. Of course, if you write that in a C++ string literal, it
- becomes <code>"/my_directory\\my_file.txt"</code>.</p>
- <p>If a drive specifier or a backslash appears
- in a pathname on a Windows system, it is always treated as the native format.</p>
- <p>Class <code>path</code> has observer functions that allow you to
- obtain the string representation of a path object in either the native format
- or the generic format. See the <a href="#Class path-iterators-etc">next section</a>
- for how that plays out.</p>
- <p>The distinction between generic format and native format is important when
- communicating with native C-style API's and with users. Both tend to expect
- paths in the native format and may be confused by the generic format. The generic
- format is great, however, for writing portable programs that work regardless
- of operating system.</p>
- <p>The next section covers class <code>path</code> observers, composition,
- decomposition, query, and iteration over the elements of a path.</p>
- <h2><a name="Class path-iterators-etc">Class path: Iterators, observers, composition, decomposition, and query</a>
- - (<a href="../example/path_info.cpp">path_info.cpp</a>)</h2>
- <p>The <code><a href="../example/path_info.cpp">path_info.cpp</a></code> program is handy for learning how class <code>path</code>
- iterators,
- observers, composition, decomposition, and query functions work on your system.
- It is one of the programs built by the <code>build.sh</code> and <code>build.bat</code>
- scripts:</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/path_info.cpp" -->#include <iostream>
- #include <boost/filesystem.hpp>
- using namespace std;
- using namespace boost::filesystem;
- const char * say_what(bool b) { return b ? "true" : "false"; }
- int main(int argc, char* argv[])
- {
- if (argc < 2)
- {
- cout << "Usage: path_info path-element [path-element...]\n"
- "Composes a path via operator/= from one or more path-element arguments\n"
- "Example: path_info foo/bar baz\n"
- # ifdef BOOST_POSIX_API
- " would report info about the composed path foo/bar/baz\n";
- # else // BOOST_WINDOWS_API
- " would report info about the composed path foo/bar\\baz\n";
- # endif
- return 1;
- }
- path p;
- for (; argc > 1; --argc, ++argv)
- p /= argv[1]; // compose path p from the command line arguments
- cout << "\ncomposed path:\n";
- cout << " operator<<()---------: " << p << "\n";
- cout << " make_preferred()-----: " << p.make_preferred() << "\n";
- cout << "\nelements:\n";
- for (auto element : p)
- cout << " " << element << '\n';
- cout << "\nobservers, native format:" << endl;
- # ifdef BOOST_POSIX_API
- cout << " native()-------------: " << p.native() << endl;
- cout << " c_str()--------------: " << p.c_str() << endl;
- # else // BOOST_WINDOWS_API
- wcout << L" native()-------------: " << p.native() << endl;
- wcout << L" c_str()--------------: " << p.c_str() << endl;
- # endif
- cout << " string()-------------: " << p.string() << endl;
- wcout << L" wstring()------------: " << p.wstring() << endl;
- cout << "\nobservers, generic format:\n";
- cout << " generic_string()-----: " << p.generic_string() << endl;
- wcout << L" generic_wstring()----: " << p.generic_wstring() << endl;
- cout << "\ndecomposition:\n";
- cout << " root_name()----------: " << p.root_name() << '\n';
- cout << " root_directory()-----: " << p.root_directory() << '\n';
- cout << " root_path()----------: " << p.root_path() << '\n';
- cout << " relative_path()------: " << p.relative_path() << '\n';
- cout << " parent_path()--------: " << p.parent_path() << '\n';
- cout << " filename()-----------: " << p.filename() << '\n';
- cout << " stem()---------------: " << p.stem() << '\n';
- cout << " extension()----------: " << p.extension() << '\n';
- cout << "\nquery:\n";
- cout << " empty()--------------: " << say_what(p.empty()) << '\n';
- cout << " is_absolute()--------: " << say_what(p.is_absolute()) << '\n';
- cout << " has_root_name()------: " << say_what(p.has_root_name()) << '\n';
- cout << " has_root_directory()-: " << say_what(p.has_root_directory()) << '\n';
- cout << " has_root_path()------: " << say_what(p.has_root_path()) << '\n';
- cout << " has_relative_path()--: " << say_what(p.has_relative_path()) << '\n';
- cout << " has_parent_path()----: " << say_what(p.has_parent_path()) << '\n';
- cout << " has_filename()-------: " << say_what(p.has_filename()) << '\n';
- cout << " has_stem()-----------: " << say_what(p.has_stem()) << '\n';
- cout << " has_extension()------: " << say_what(p.has_extension()) << '\n';
- return 0;
- }<!-- end include file --></pre>
- </td>
- </tr>
- </table>
- <p>Run the examples below on your system, and try some different path arguments
- as we go along. Here is the invocation we will talk about in detail:</p>
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Ubuntu Linux </b></i></td>
- </tr>
- <tr>
- <td>
- <pre>$ ./path_info /foo bar baa.txt
- composed path:
- operator<<()---------: "/foo/bar/baa.txt"
- make_preferred()-----: "/foo/bar/baa.txt"
- elements:
- "/"
- "foo"
- "bar"
- "baa.txt"
- observers, native format:
- native()-------------: /foo/bar/baa.txt
- c_str()--------------: /foo/bar/baa.txt
- string()-------------: /foo/bar/baa.txt
- wstring()------------: /foo/bar/baa.txt
- observers, generic format:
- generic_string()-----: /foo/bar/baa.txt
- generic_wstring()----: /foo/bar/baa.txt
- decomposition:
- root_name()----------: ""
- root_directory()-----: "/"
- root_path()----------: "/"
- relative_path()------: "foo/bar/baa.txt"
- parent_path()--------: "/foo/bar"
- filename()-----------: "baa.txt"
- stem()---------------: "baa"
- extension()----------: ".txt"
- query:
- empty()--------------: false
- is_absolute()--------: true
- has_root_name()------: false
- has_root_directory()-: true
- has_root_path()------: true
- has_relative_path()--: true
- has_parent_path()----: true
- has_filename()-------: true
- has_stem()-----------: true
- has_extension()------: true</pre>
- </td>
- </tr>
- </table>
-
- <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td align="center"><i><b>Microsoft Windows</b></i></td>
- </tr>
- <tr>
- <td>
- <pre>>path_info \foo bar baa.txt
- composed path:
- operator<<()---------: "\foo\bar\baa.txt"
- make_preferred()-----: "\foo\bar\baa.txt"
- elements:
- "/"
- "foo"
- "bar"
- "baa.txt"
- observers, native format:
- native()-------------: \foo\bar\baa.txt
- c_str()--------------: \foo\bar\baa.txt
- string()-------------: \foo\bar\baa.txt
- wstring()------------: \foo\bar\baa.txt
- observers, generic format:
- generic_string()-----: /foo/bar/baa.txt
- generic_wstring()----: /foo/bar/baa.txt
- decomposition:
- root_name()----------: ""
- root_directory()-----: "\"
- root_path()----------: "\"
- relative_path()------: "foo\bar\baa.txt"
- parent_path()--------: "\foo\bar"
- filename()-----------: "baa.txt"
- stem()---------------: "baa"
- extension()----------: ".txt"
- query:
- empty()--------------: false
- is_absolute()--------: false
- has_root_name()------: false
- has_root_directory()-: true
- has_root_path()------: true
- has_relative_path()--: true
- has_parent_path()----: true
- has_filename()-------: true
- has_stem()-----------: true
- has_extension()------: true</pre>
- </td>
- </tr>
- </table>
- <p>We will go through the above code in detail to gain a better
- understanding of what is going on.</p>
- <p dir="ltr">A common need is to compose a path from its constituent
- directories. Class <code>path</code> uses <code>/</code> and <code>/=</code> operators to
- append elements. That's a reminder
- that these operations append the operating system's preferred directory
- separator if needed. The preferred
- directory separator is a slash on POSIX-like systems, and a backslash on
- Windows-like systems.</p>
- <p dir="ltr">That's what this code does before displaying the resulting <code>
- path p</code> using the <code>class path</code> stream inserter: </p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/path_info.cpp" --> path p;
- for (; argc > 1; --argc, ++argv)
- p /= argv[1]; // compose path p from the command line arguments
- cout << "\ncomposed path:\n";
- cout << " operator<<()---------: " << p << "\n";
- cout << " make_preferred()-----: " << p.make_preferred() << "\n";</pre>
- </td>
- </tr>
- </table>
- <p>One abstraction for thinking about a path is as a sequence of elements, where
- the elements are directory and file names. To support this abstraction, class
- <code>path</code> provides STL-like iterators and also <code>begin()</code>
- and <code>end()</code> functions.</p>
- <p>Here is the code that produced the list of elements in the above output listing:</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre>cout << "\nelements:\n";
- for (auto element : p)
- cout << " " << element << '\n';</pre>
- </td>
- </tr>
- </table>
- <p>Let's look at class path observer functions:</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/path_info.cpp" --> cout << "\nobservers, native format:" << endl;
- # ifdef BOOST_POSIX_API
- cout << " native()-------------: " << p.native() << endl;
- cout << " c_str()--------------: " << p.c_str() << endl;
- # else // BOOST_WINDOWS_API
- wcout << L" native()-------------: " << p.native() << endl;
- wcout << L" c_str()--------------: " << p.c_str() << endl;
- # endif
- cout << " string()-------------: " << p.string() << endl;
- wcout << L" wstring()------------: " << p.wstring() << endl;
- cout << "\nobservers, generic format:\n";
- cout << " generic_string()-----: " << p.generic_string() << endl;
- wcout << L" generic_wstring()----: " << p.generic_wstring() << endl;</pre>
- </td>
- </tr>
- </table>
- <p>Native format observers should be used when interacting with the
- operating system or with users; that's what they expect.</p>
- <p>Generic format observers should be used when the results need to be
- portable and uniform regardless of the operating system.</p>
- <p><code>path</code> objects always hold pathnames in the native
- format, but otherwise leave them unchanged from their source. The
- <a href="reference.html#preferred">preferred()</a> function will convert to the
- preferred form, if the native format has several forms. Thus on Windows, it will
- convert slashes to backslashes.</p>
- <p>Moving on to decomposition:</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/path_info.cpp" --> cout << "\ndecomposition:\n";
- cout << " root_name()----------: " << p.root_name() << '\n';
- cout << " root_directory()-----: " << p.root_directory() << '\n';
- cout << " root_path()----------: " << p.root_path() << '\n';
- cout << " relative_path()------: " << p.relative_path() << '\n';
- cout << " parent_path()--------: " << p.parent_path() << '\n';
- cout << " filename()-----------: " << p.filename() << '\n';
- cout << " stem()---------------: " << p.stem() << '\n';
- cout << " extension()----------: " << p.extension() << '\n';</pre>
- </td>
- </tr>
- </table>
- <p> And, finally, query functions:</p>
- <table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF">
- <tr>
- <td>
- <pre><!-- include file "../example/path_info.cpp" --> cout << "\nquery:\n";
- cout << " empty()--------------: " << say_what(p.empty()) << '\n';
- cout << " is_absolute()--------: " << say_what(p.is_absolute()) << '\n';
- cout << " has_root_name()------: " << say_what(p.has_root_name()) << '\n';
- cout << " has_root_directory()-: " << say_what(p.has_root_directory()) << '\n';
- cout << " has_root_path()------: " << say_what(p.has_root_path()) << '\n';
- cout << " has_relative_path()--: " << say_what(p.has_relative_path()) << '\n';
- cout << " has_parent_path()----: " << say_what(p.has_parent_path()) << '\n';
- cout << " has_filename()-------: " << say_what(p.has_filename()) << '\n';
- cout << " has_stem()-----------: " << say_what(p.has_stem()) << '\n';
- cout << " has_extension()------: " << say_what(p.has_extension()) << '\n';</pre>
- </td>
- </tr>
- </table>
- <p>These are pretty self-evident, but do note the difference in the
- result of <code>is_absolute()</code> between Linux and Windows. Because there is
- no root name (i.e. drive specifier or network name), a lone slash (or backslash)
- is a relative path on Windows but an absolute path on POSIX-like operating
- systems. </p>
- <h2><a name="Error-reporting">Error reporting</a></h2>
- <p>The Boost.Filesystem <code>file_size</code> function, like many of the
- operational functions, has two overloads:</p>
- <blockquote>
- <pre>uintmax_t <a name="file_size">file_size</a>(const path& p);
- uintmax_t <a name="file_size2">file_size</a>(const path& p, system::error_code& ec);</pre>
- </blockquote>
- <p>The only significant difference between the two is how they report errors.</p>
- <p>The
- first signature will throw exceptions to report errors. A <code>
- <a href="reference.html#Class-filesystem_error">filesystem_error</a></code> exception will be thrown
- on an
- operational error. <code>filesystem_error</code> is derived from <code>std::runtime_error</code>.
- It has a
- member function to obtain the <code>
- <a href="../../system/doc/reference.html#Class-error_code">error_code</a></code> reported by the source
- of the error. It also has member functions to obtain the path or paths that caused
- the error.</p>
- <blockquote>
- <p><b>Motivation for the second signature:</b> Throwing exceptions on errors was the entire error reporting story for the earliest versions of
- Boost.Filesystem, and indeed throwing exceptions on errors works very well for
- many applications. But user reports trickled in that some code became so
- littered with try and catch blocks as to be unreadable and unmaintainable. In
- some applications I/O errors aren't exceptional, and that's the use case for
- the second signature.</p>
- </blockquote>
- <p>Functions with a <code>system::error_code&</code> argument set that
- argument to report operational error status, and so do not throw exceptions when I/O
- related errors occur. For a full explanation, see
- <a href="reference.html#Error-reporting">Error reporting</a> in the reference
- documentation. </p>
- <hr>
- <p>© Copyright Beman Dawes 2010, 2015</p>
- <p>Distributed under the Boost Software License, Version 1.0. See
- <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
- <p>Revised
- <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->07 August 2017<!--webbot bot="Timestamp" endspan i-checksum="31490" --></p>
- </body>
- </html>
|