This post is extremely late, but it’s still worth mentioning. A few weeks ago I did all the necessary work to get the Rosella FileSystem library listed as stable. “Stable”, as always, doesn’t mean the library is perfect. Instead, it means that the library has a stable design, a generally stable interface, and it’s usable right now by anybody who is interested to try it out.
Parrot offers some tools for working with files and directories. Mostly,
these tools involve use of the OS PMC, a dynamically-loaded PMC type that is
not built in to Parrot core. For simple IO operations on files Parrot does
provide the FileHandle PMC type, but for things like working with the
organization of files and directories you need to use OS. Also, the OS PMC
doesn’t quite do everything either. There is also a dynamically-loaded ops
library that provides a stat
wrapper op, in addition to some other
convenience ops for working with FileHandles (if the methods on FileHandle to
do the exact same things are inexplicably not what you needed).
What Rosella FileSystem library does is provide nicer, friendlier wrappers
around all these things. The library itself is pretty heavily inspired by
System.IO
from the .NET standard library, and some items from Python’s
os
module too.
Files and directories are all instances of Rosella.FileSystem.Entry
. There
are two subclasses: Rosella.FileSystem.File
and
Rosella.FileSystem.Directory
. You can create instances of these objects
using simple constructors with path strings. Here are some Winxed code
examples:
var file = new Rosella.FileSystem.File("foo.txt");
var dir = new Rosella.FileSystem.Directory("bar");
Or, if you want to create a file in a directory, you can do something like this:
var dir = new Rosella.FileSystem.Directory("bar");
var file = new Rosella.FileSystem.File("foo.txt", dir);
All Entry
objects have some common methods:
entry.exists() # 1 if it exists. 0 otherwise
entry.delete() # Delete (non-recursive delete for Directories)
entry.rename("baz") # Rename it
string n = entry.short_name() # The short-name of the entry (no path)
Directories add in a few other features:
dir.delete_recursive() # Delete with all contents
dir.create() # Create it, if it doesn't exist
var files = dir.get_files() # Get a list of all File objects in it
var dirs = dir.get_subdirectories() # Get a list of all Directories in it
var entries = dir.get_entries() # Get all entries, File and Directory
var entry = dir["foo.txt"] # Get the entry by name. File or Directory
var entry = dir["baz"] # Same
dir.walk(visitor) # Walk contents, using a Visitor
dir.walk_func(func) # Walk contents, using a Sub on each File
exists dir["foo"] # Determine if "foo" exists
delete dir["foo"] # Delete "foo", if it exists
Files likewise add in some features of their own:
var fh = file.open_read() # Get FileHandle, opened for reading
var fh = file.open_write() # Get FileHandle, opened for writing
var fh = file.open_append() # Get FileHandle, open for write/append
string t = file.read_all_text() # Read all text into a single string
var t = file.read_all_lines() # Read all text, as an array of lines
file.write_all_text(txt) # Write all text to the file (delete existing contents)
file.write_all_lines(t) # Write an array of string lines to file
file.append_text(t) # Append some text
file.copy(dest) # Copy a file to dest
Basically, it’s a very easy object-oriented interface to common file system operations. It’s nothing fancy, and there are some features missing which people might expect, but it’s very useful and, I think, very usable. Also, it’s not a very thick library so while there is some performance overhead it isn’t too much considering the added convenience.