FileSystem
new FileSystem(path) creates an instance of filesystem at path.
IFileSystem fs = new FileSystem(@"C:\Temp\");
.Browse(path) returns a snapshot of directory contents.
IDirectoryContent contents = fs.Browse("C:/Windows/");
IDirectoryContent is enumerable IEnumerable<IEntry>.
foreach (IEntry entry in fs.Browse("C:/Windows/"))
Console.WriteLine(entry.Path);
.AssertExists() asserts that directory exists. It throws DirectoryNotFound if not found.
foreach (var entry in fs.Browse("C:/Windows/").AssertExists())
Console.WriteLine(entry.Path);
.GetEntry(path) reads a single file or directory entry. Returns null if entry is not found.
IEntry e = FileSystem.OS.GetEntry("C:/Windows/win.ini");
Console.WriteLine(e.Path);
.AssertExists() asserts that null is not returned. Throws FileNotFoundException if entry was not found.
IEntry e = FileSystem.OS.GetEntry("C:/Windows/win.ini").AssertExists();
Files can be opened for reading.
using (Stream s = fs.Open("file.txt", FileMode.Open, FileAccess.Read, FileShare.Read))
{
Console.WriteLine(s.Length);
}
And for for writing.
using (Stream s = fs.Open("somefile.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
s.WriteByte(32);
}
Directories can be created.
fs.CreateDirectory("dir/");
Directories can be deleted.
fs.Delete("dir/", recurse: true);
Files and directories can be renamed and moved.
fs.CreateDirectory("dir/");
fs.Move("dir/", "new-name/");
And file attributes changed.
fs.SetFileAttribute("myfile", FileAttributes.ReadOnly);
Singleton
The singleton instance FileSystem.OS refers to a filesystem at the OS root.
IFileSystem fs = FileSystem.OS;
Extension method .VisitTree() visits filesystem. On root path "" FileSystem.OS returns drive letters.
foreach (var line in FileSystem.OS.VisitTree(depth: 2))
Console.WriteLine(line);
"" ├──"C:" │ ├── "hiberfil.sys" │ ├── "pagefile.sys" │ ├── "swapfile.sys" │ ├── "Documents and Settings" │ ├── "Program Files" │ ├── "Program Files (x86)" │ ├── "System Volume Information" │ ├── "Users" │ └── "Windows10" └──"D:"
Note
The separator character is always forward slash '/'. For example "C:/Windows/win.ini".
Extension method .PrintTo() appends the visited filesystem to text output.
FileSystem.OS.PrintTo(Console.Out, depth: 2, format: PrintTree.Format.DefaultPath);
├── C:/ │ ├── C:/hiberfil.sys │ ├── C:/pagefile.sys │ ├── C:/swapfile.sys │ ├── C:/Documents and Settings/ │ ├── C:/Program Files/ │ ├── C:/Program Files (x86)/ │ ├── C:/System Volume Information/ │ ├── C:/Users/ │ └── C:/Windows/ └── D:/
On linux FileSystem.OS returns slash '/' root.
FileSystem.OS.PrintTo(Console.Out, depth: 3, format: PrintTree.Format.DefaultPath);
└──/ ├──/bin/ ├──/boot/ ├──/dev/ ├──/etc/ ├──/lib/ ├──/media/ ├──/mnt/ ├──/root/ ├──/sys/ ├──/usr/ └──/var/
FileSystem.Application refers to the application's root directory.
FileSystem.Application.PrintTo(Console.Out);
"" ├── "Application.dll" ├── "Application.runtimeconfig.json" ├── "Lexical.FileSystem.Abstractions.dll" └── "Lexical.FileSystem.dll"
FileSystem.Temp refers to the running user's temp directory.
FileSystem.Temp.PrintTo(Console.Out, depth: 1);
"" ├── "dmk55ohj.jjp" ├── "wrz4cms5.r2f" └── "18e1904137f065db88dfbd23609eb877"
Singleton instances:
Name | Description | On Windows | On Linux |
---|---|---|---|
FileSystem.OS | Operating system root. | "" | "" |
FileSystem.Application | Running application's base directory. | ||
FileSystem.UserProfile | The user's profile folder. | "C:\Users\<user>" | "/home/<user>" |
FileSystem.MyDocuments | The My Documents folder. | "C:\Users\<user>\Documents" | "/home/<user>" |
FileSystem.Personal | A common repository for documents. | "C:\Users\<user>\Documents" | "/home/<user>" |
FileSystem.Temp | Running user's temp directory. | "C:\Users\<user>\AppData\Local\Temp" | "/tmp |
FileSystem.Config | User's cloud-sync program configuration (roaming data). | "C:\Users\<user>\AppData\Roaming" | "/home/<user>/.config" |
FileSystem.Data | User's local program data. | "C:\Users\<user>\AppData\Local" | "/home/<user>/.local/share" |
FileSystem.ProgramData | Program data that is shared with every user. | "C:\ProgramData" | "/usr/share" |
FileSystem.Desktop | User's desktop. | "C:\Users\<user>\Desktop" | "/home/user/Desktop" |
FileSystem.MyPictures | User's pictures. | "C:\Users\<user>\Pictures" | "/home/user/Pictures" |
FileSystem.MyVideos | User's videos. | "C:\Users\<user>\Videos" | "/home/user/Videos" |
FileSystem.MyMusic | User's music. | "C:\Users\<user>\Music" | "/home/user/Music" |
FileSystem.Templates | Templates. | "C:\Users\<user>\AppData\Roaming\Microsoft\Windows\Templates" | "/home/user/Templates" |
IFileEntry.PhysicalPath() returns physical path of file entry.
foreach(var line in FileSystem.Temp.VisitTree(depth:2))
Console.WriteLine(line.Entry.PhysicalPath());
TreeVisitor prints physical path with PrintTree.Format.PhysicalPath flag.
FileSystem.Temp.PrintTo(
output: Console.Out,
depth: 2,
format: PrintTree.Format.Default | PrintTree.Format.PhysicalPath);
"" [C:\Users\\user\\AppData\Local\Temp\] ├── "dmk55ohj.jjp" [C:\Users\\user\\AppData\Local\Temp\dmk55ohj.jjp] ├── "wrz4cms5.r2f" [C:\Users\\user\\AppData\Local\Temp\wrz4cms5.r2f] └── "18e1904137f065db88dfbd23609eb877" [C:\Users\\user\\AppData\Local\Temp\18e1904137f065db88dfbd23609eb877]
Observing
Files and directories can be observed for changes.
IObserver<IEvent> observer = new Observer();
IFileSystemObserver handle = FileSystem.OS.Observe("C:/**", observer);
Observer can be used in a using scope.
using (var handle = FileSystem.Temp.Observe("*.dat", new PrintObserver()))
{
FileSystem.Temp.CreateFile("file.dat", new byte[] { 32, 32, 32, 32 });
FileSystem.Temp.Delete("file.dat");
Thread.Sleep(1000);
}
class PrintObserver : IObserver<IEvent>
{
public void OnCompleted() => Console.WriteLine("OnCompleted");
public void OnError(Exception error) => Console.WriteLine(error);
public void OnNext(IEvent @event) => Console.WriteLine(@event);
}
StartEvent(C:\Users\\<i><user></i>\\AppData\Local\Temp\, 23.10.2019 16.27.01 +00:00)
CreateEvent(C:\Users\\<i><user></i>\\AppData\Local\Temp\, 23.10.2019 16.27.01 +00:00, file.dat)
ChangeEvent(C:\Users\\<i><user></i>\\AppData\Local\Temp\, 23.10.2019 16.27.01 +00:00, file.dat)
DeleteEvent(C:\Users\\<i><user></i>\\AppData\Local\Temp\, 23.10.2019 16.27.01 +00:00, file.dat)
OnCompleted
Disposing
Disposable objects can be attached to be disposed along with FileSystem.
// Init
object obj = new ReaderWriterLockSlim();
IFileSystemDisposable fs = new FileSystem("").AddDisposable(obj);
// ... do work ...
// Dispose both
fs.Dispose();
Delegates can be attached to be executed at dispose of FileSystem.
IFileSystemDisposable fs = new FileSystem("")
.AddDisposeAction(f => Console.WriteLine("Disposed"));
.BelateDispose() creates a handle that postpones dispose on .Dispose(). Actual dispose will proceed once .Dispose() is called and all belate handles are disposed. This can be used for passing the IFileSystem to a worker thread.
FileSystem fs = new FileSystem("");
fs.Browse("");
// Postpone dispose
IDisposable belateDisposeHandle = fs.BelateDispose();
// Start concurrent work
Task.Run(() =>
{
// Do work
Thread.Sleep(1000);
fs.GetEntry("");
// Release belate handle. Disposes here or below, depending which thread runs last.
belateDisposeHandle.Dispose();
});
// Start dispose, but postpone it until belatehandle is disposed in another thread.
fs.Dispose();