Add structured project documentation

This commit is contained in:
2026-02-28 19:10:04 +01:00
parent ee19f2362e
commit 08a0d2f382
6 changed files with 772 additions and 0 deletions

205
docs/usage.md Normal file
View File

@@ -0,0 +1,205 @@
# Usage
## Quick Start
### Create a Root Filesystem
```csharp
using System.IO;
using VirtualFS;
using VirtualFS.Implementation;
using VirtualFS.Memory;
using VirtualFS.Physical;
var root = new RootFileSystem();
var physical = new PhysicalFileSystem(new DirectoryInfo("/srv/site"));
var generated = new MemoryFileSystem
{
Priority = FileSystemMountPriority.High
};
root.Mount(physical, "/");
root.Mount(generated, "/");
```
In this setup:
- files present in `generated` can override files from `physical`
- reads are resolved through the root
- writes go to the writable backend chosen for the path
## Creating and Reading Files
```csharp
var file = root.Root.FileCreate("hello.txt");
file.WriteAllText("Hello from VirtualFS");
string text = root.GetFile("/hello.txt").ReadAllText();
```
## Working Inside a Mounted Subtree
```csharp
root.Mount(new MemoryFileSystem(), "/cache/");
var cacheDir = root.GetDirectory("/cache/");
cacheDir.Create("images");
cacheDir.GetDirectory("images/").FileCreate("thumb.txt").WriteAllText("ok");
```
## Overlay Example
```csharp
using System.IO;
using VirtualFS;
using VirtualFS.Compressed;
using VirtualFS.Implementation;
using VirtualFS.Physical;
var root = new RootFileSystem();
var baseAssets = new ZipReadFileSystem(System.IO.File.OpenRead("base-assets.zip"))
{
Priority = FileSystemMountPriority.Low
};
var overrides = new PhysicalFileSystem(new DirectoryInfo("./overrides"))
{
Priority = FileSystemMountPriority.High
};
root.Mount(baseAssets, "/assets/");
root.Mount(overrides, "/assets/");
```
Reads under `/assets/` prefer files from `./overrides`, then fall back to the ZIP.
## Enumerating Entries
```csharp
foreach (var entry in root.Root.GetEntries())
{
Console.WriteLine($"{entry.FullPath} readonly={entry.IsReadOnly}");
}
```
You can also enumerate only files or only directories:
- `GetFiles()`
- `GetDirectories()`
All enumeration methods support an optional regular-expression filter.
## Using `Directory`
Common operations:
- `GetEntries()`
- `GetFiles()`
- `GetDirectories()`
- `Exists(name)`
- `GetEntry(name)`
- `GetFile(name)`
- `GetDirectory(name)`
- `Create(name)`
- `FileCreate(name)`
- `Delete(recursive)`
Example:
```csharp
var dir = root.GetDirectory("/content/");
if (!dir.Exists("images/"))
dir.Create("images");
var imageDir = dir.GetDirectory("images/");
```
## Using `File`
Common operations:
- `OpenRead()`
- `OpenWrite()`
- `ReadAllBytes()`
- `ReadAllLines()`
- `ReadAllText()`
- `WriteAllBytes()`
- `WriteAllLines()`
- `WriteAllText()`
- `AppendAllBytes()`
- `AppendAllLines()`
- `AppendAllText()`
- `Delete()`
Example:
```csharp
var file = root.GetFile("/config/appsettings.json");
var text = file.ReadAllText();
```
## `forceLocal`
Many `Directory` and `File` instance methods accept `forceLocal`.
Use it when:
- you explicitly want to bypass the root overlay behavior
- you want to operate only inside the backend that produced the entry
Example:
```csharp
var entry = root.GetFile("/assets/logo.png");
using var localStream = entry.OpenRead(forceLocal: true);
```
## Path Examples
```csharp
Path dir = "/docs/";
Path file = dir + "readme.txt"; // "/docs/readme.txt"
Path parent = ((Path)"/docs/api/").Parent; // "/docs/"
```
Normalization:
- `"/a/./b.txt"` becomes `"/a/b.txt"`
- `"/a/b/../c.txt"` becomes `"/a/c.txt"`
## Copy, Move, Rename
Available on `IFileSystem`:
- `Copy`
- `Move`
- `ReName`
Notes:
- copy and move may work across different mounted backends
- cross-backend operations may be slower
- directory destinations are expected to be directory paths
## Unmounting
`Umount` succeeds only if the filesystem is not busy.
That means:
- open file streams must be closed first
- callers should use `using` or explicit disposal
Example:
```csharp
using (var stream = root.GetFile("/data/report.txt").OpenRead())
{
// use stream
}
root.Umount(someFs);
```