FileSystem
FileSystem
is a filesystem interface.
You can access the native filesystem by calling FileSystem::native()
.
A FileSystem
object expects either Windows paths or POSIX-style paths, depending on its
implementation. The NativePath
class always manipulate paths in the appropriate format for the
native filesystem. When working with an abstract FileSystem
where the path format is unknown,
pathFormat()
will return a PathFormat
object suitable for manipulating paths in the expected
format. See Manipulating Paths for more information.
You can create a virtual filesystem by calling createVirtual()
, or even implement your own.
Virtual filesystems don't necessarily support all the member functions in the FileSystem
interface.
Result Codes
Most FileSystem
member functions update an internal result code. This result code is stored in a
thread-local variable of type FSResult
. Some member functions, such as makeDir()
, return the
result code explicitly. Other member functions, such as loadTextAutodetect()
, do not return the
result code explicitly. You can always access the last result code by calling lastResult()
.
Note that, because the internal result code is thread-local, it's shared across all FileSystem
instances. For example, an operation on a virtual filesystem will update the result code for the
native filesystem, and vice versa.
In some cases, a function may set the result code to Unknown
instead of one of the result codes
documented here. Such cases mean that Plywood needs to be updated to recognize the underlying error.
Header File
#include <ply-runtime/filesystem/FileSystem.h>
Also included from <ply-runtime/Base.h>
.
Member Functions
-
Returns a
FileSystem
object that interacts with the native filesystem. -
Returns a
PathFormat
describing the filesystem's expected path format. This object can be used to manipulate paths in the expected format. -
Sets the working directory of the process in the target filesystem. May not be supported in virtual filesystems.
This function updates the internal result code. The result code is also returned directly. Expected result codes are
OK
orNotFound
. -
Gets the working directory of the process in the target filesystem.
This function updates the internal result code. The expected result code is
OK
. -
Returns the last result code.
-
Sets the last result code.
-
Checks whether a file or directory with the specified pathname exists. The return value is one of
File
,Directory
orNotFound
.This function does not update the internal result code.
-
Returns
true
ifpath
specifies the name of a directory. Shorthand forexists(path) == ExistsResult::Directory
.This function does not update the internal result code.
-
Returns a
Directory
object. TheDirectory
object can be used in a range-based for loop to enumerate the contents of a directory. Such a range-based for loop iterates over a sequence ofDirectoryEntry
objects. It is recommended to iterate by reference in order to avoid copying theDirectoryEntry
object. EachDirectoryEntry
takes the following form:struct DirectoryEntry { String name; bool isDir; u64 fileSize; // Only valid if WithSizes was specified double creationTime; // Only valid if WithTimes was specified double accessTime; double modificationTime; };
The entries are returned in an arbitrary order, and the special directory entries
"."
and".."
are not enumerated.The
flags
argument accepts a bitwise-or of zero or more of the following values:FileSystem::WithSizes
FileSystem::WithFlags
The
fileSize
member ofDirectoryEntry
is only valid ifWithSizes
was set. ThecreationTime
,accessTime
andmodificationTime
members are only valid ifWithTimes
was set. Using these flags is likely faster than callinggetFileStatus()
on the individual files, especially on Windows. Conversely, if the additional information is not needed, it might be faster to omit these flags on some platforms.The following example outputs a list of non-directory files in the current directory:
OutStream outs = StdOut::text(); for (const DirectoryEntry& entry : FileSystem::native()->listDir(".", 0)) { if (!entry.isDir) { outs << entry.name << '\n'; } }
The initial call to
listDir()
updates the internal result code. Expected result codes areOK
,NotFound
orAccessDenied
. Each iteration of the loop updates the internal result code as well. Expected result codes areOK
orNotFound
(if, for example, the volume was removed during iteration). -
Similar to
os.walk()
in Python. Returns aFileSystem::Walk
object. TheFileSystem::Walk
object can be used in a range-based for loop to enumerate the contents of a directory tree. Such a range-based for loop iterates over a sequence ofWalkTriple
objects, with oneWalkTriple
object for each directory in the tree rooted attop
. It is recommended to iterate by reference in order to avoid copying theWalkTriple
object. EachWalkTriple
takes the following form:struct WalkTriple { struct FileInfo { String name; u64 fileSize; // Only valid if WithSizes was specified double creationTime; // Only valid if WithTimes was specified double accessTime; double modificationTime; }; String dirPath; Array<String> dirNames; Array<FileInfo> files; };
dirPath
contains the path to the directory.dirNames
is a list of the names of the subdirectories indirPath
excluding"."
and".."
.files
is a list ofWalkTriple::FileInfo
objects for the non-directory files indirPath
.On each iteration of the loop, the caller can modify the
dirNames
list in-place, andwalk()
will only recurse into the subdirectories whose names remain indirNames
. This can be used to prune the search, impose a specific order of visiting, or informwalk()
about directories that the caller creates or renames.The
flags
argument accepts a bitwise-or of zero or more of the following values:FileSystem::WithSizes
FileSystem::WithFlags
The
fileSize
member ofWalkTriple::FileInfo
is only valid ifWithSizes
was set. ThecreationTime
,accessTime
andmodificationTime
members are only valid ifWithTimes
was set. Using these flags is likely faster than callinggetFileStatus()
on the individual files, especially on Windows. Conversely, if the additional information is not needed, it might be faster to omit these flags on some platforms.The following example displays the number of bytes taken by non-directory files in each directory under the starting directory, except that it doesn't look under any subdirectory that starts with a dot
"."
:OutStream outs = StdOut::text(); for (WalkTriple& triple : fs->walk(".", FileSystem::WithSizes)) { // Calculate the number of bytes taken by non-directory files u64 sum = 0; for (const WalkTriple::FileInfo& file : triple.files) { sum += file.fileSize; } outs.format("{}: {} bytes\n", triple.dirPath, sum); // Prune subdirectories that start with "." for (u32 i = 0; i < triple.dirNames.numItems(); i++) { if (triple.dirNames[i].startsWith(".")) { triple.dirNames.erase(i); i--; } } }
The initial call to
walk()
updates the internal result code. Expected result codes areOK
,NotFound
orAccessDenied
. Each iteration of the loop updates the internal result code as well. Expected result codes areOK
,NotFound
(if, for example, the volume was removed during iteration) orAccessDenied
. -
Creates a new directory. The parent directory must already exist.
This function updates the internal result code. The result code is also returned directly. Expected result codes are
OK
,AlreadyExists
orAccessDenied
. -
Recursive directory creation function. Like
makeDir()
, but creates all intermediate-level directories needed to contain the leaf directory. Similar toos.makedirs()
in Python.This function updates the internal result code. The result code is also returned directly. Expected result codes are
OK
orAccessDenied
. -
Renames the file at
srcPath
todstPath
. IfdstPath
already exists and is a file, it will be silently replaced.This function updates the internal result code. The result code is also returned directly.
-
Deletes the file at
path
.This function updates the internal result code. The result code is also returned directly.
-
Removes the directory tree at
path
. The specified directory and all of its contents are deleted recursively.This function updates the internal result code. The result code is also returned directly. Expected result codes are
OK
orAccessDenied
. -
Returns a
FileStatus
object for the file located atpath
.FileStatus
contains the following members:struct FileStatus { FSResult result; // Result of getFileStatus() u64 fileSize; // Size of the file in bytes double creationTime; // The file's POSIX creation time double accessTime; // The file's POSIX access time double modificationTime; // The file's POSIX modification time };
creationTime
,accessTime
andmodificationTime
are expressed in POSIX time, which is the number of seconds since January 1, 1970.This function updates the internal result code. The result code is also returned in the
result
member. Expected result codes areOK
orNotFound
. -
Returns an
InPipe
that reads the raw contents of the specified file, ornullptr
if the file could not be opened.This function updates the internal result code. Expected result codes are
OK
,NotFound
,AccessDenied
orLocked
.InPipe
is a low-level class that doesn't perform any application-level buffering. If you plan to read small amounts of data at a time, such when parsing a text or binary file format, it is suggested to wrap the returnedInPipe
in anInStream
. TheopenStreamForRead()
convenience function is provided for this. -
Returns an
OutPipe
that writes raw data to the specified file, ornullptr
if the file could not be opened.This function updates the internal result code. Expected result codes are
OK
,NotFound
,AccessDenied
orLocked
.OutPipe
is a low-level class that doesn't perform any application-level buffering. If you plan to write small amounts of data at a time, such when writing a text or binary file format, it is suggested to wrap the returnedOutPipe
in anOutStream
. TheopenStreamForWrite()
convenience function is provided for this. -
Returns an
InStream
that reads the raw contents of the specified file, ornullptr
if the file could not be opened.This function updates the internal result code. Expected result codes are
OK
,NotFound
orLocked
. -
Returns an
OutStream
that writes raw data to the specified file, ornullptr
if the file could not be opened.This function updates the internal result code. Expected result codes are
OK
,NotFound
,AccessDenied
orLocked
. -
Returns an
InStream
that reads raw data from the specified text file and converts it to UTF-8 with Unix-style newlines, ornullptr
if the file could not be opened. The text file is expected to have the file format described bytextFormat
. Any byte order mark (BOM) in the file is skipped. SeeTextFormat
for more information on supported text file formats.This function updates the internal result code. Expected result codes are
OK
,NotFound
,AccessDenied
orLocked
.The
openTextForRead()
function is equivalent to the following:Owned<InStream> ins = fs->openStreamForRead(path); if (!ins) return nullptr; return textFormat.createImporter(std::move(ins));
-
Returns a
Tuple
. The first tuple item is aInStream
that reads raw data from the specified text file and converts it to UTF-8 with Unix-style newlines, ornullptr
if the file could not be opened. The text file format is detected automatically and returned as the second tuple item. Any byte order mark (BOM) in the text file is skipped. SeeTextFormat
for more information on supported text file formats.This function updates the internal result code. Expected result codes are
OK
,NotFound
,AccessDenied
orLocked
.The
openTextForReadAutodetect()
function is equivalent to the following:Owned<InStream> ins = fs->openStreamForRead(path); if (!ins) return {nullptr, TextFormat{}}; TextFormat textFormat = TextFormat::autodetect(ins); return {textFormat.createImporter(std::move(ins)), textformat};
-
Returns a
String
containing the raw contents of the specified file, or an emptyString
if the file could not be opened.To check if the file was opened successfuly, call
lastResult()
. Expected result codes areOK
,NotFound
,AccessDenied
orLocked
. -
Returns a
String
containing the contents of the specified text file converted to UTF-8 with Unix-style newlines, or an emptyString
if the file could not be opened. The text file is expected to have the file format described bytextFormat
. Any byte order mark (BOM) in the text file is skipped. SeeTextFormat
for more information on supported text file formats.To check if the file was opened successfuly, call
lastResult()
. Expected result codes areOK
,NotFound
,AccessDenied
orLocked
. -
Returns a
Tuple
. The first tuple item is aString
containing the contents of the specified text file converted to UTF-8 with Unix-style newlines, or an emptyString
if the file could not be opened. The text file format is detected automatically and returned as the second tuple item. Any byte order mark (BOM) in the text file is skipped. SeeTextFormat
for more information on supported text file formats.To check if the file was opened successfuly, call
lastResult()
. Expected result codes areOK
,NotFound
,AccessDenied
orLocked
. -
Returns an
OutStream
that writes text to the specified text file in the specified format, ornullptr
if the file could not be opened. TheOutStream
expects UTF-8-encoded text. TheOutStream
accepts both Windows and Unix-style newlines; all newlines will be converted to the format described bytextFormat
. SeeTextFormat
for more information on supported text file formats.This function updates the internal result code. Expected result codes are
OK
,NotFound
,AccessDenied
orLocked
.The
openTextForWrite()
function is equivalent to the following:Owned<OutStream> outs = fs->openTextForWrite(path); if (!outs) return nullptr; return TextFormat::createExporter(std::move(outs), textFormat);
-
First, this function tries to load the raw contents of the specified file. If the load succeeds and its raw contents match
contents
exactly, the function returnsUnchanged
. Otherwise, if the parent directories ofpath
don't exist, it attempts to create them. If that succeeds, it savescontents
to a temporary file in the same folder aspath
. If that succeeds, it renames the temporary file topath
, replacing any original contents.In all cases, this function updates the internal result code. The result code is also returned directly.
FSResult FileSystem::makeDirsAndSaveTextIfDifferent(StringView path, StringView strContents, const TextFormat& textFormat)
[code]-
First, this function converts
strContents
to a raw memory buffer using the text file format specified bytextFormat
. Then, it tries to load the raw contents of the specified file. If the load succeeds and its raw contents match the contents of the raw memory buffer exactly, the function returnsUnchanged
. Otherwise, if the parent directories ofpath
don't exist, it attempts to create them. If that succeeds, it saves the raw memory buffer to a temporary file in the same folder aspath
. If that succeeds, it renames the temporary file topath
, replacing any original contents. SeeTextFormat
for more information on supported text file formats.In all cases, this function updates the internal result code. The result code is also returned directly.
-
Creates a virtual
FileSystem
that acts entirely within the directory specified byrootPath
.The result virtual
FileSystem
works with POSIX-style paths, doesn't implementgetWorkingDirectory
orsetWorkingDirectory
, and doesn't accept absolute paths as arguments to any of its member functions. Some of those restrictions might be removed in the future.