Cocoar.FileSystem
0.1.0-alpha.12
See the version list below for details.
dotnet add package Cocoar.FileSystem --version 0.1.0-alpha.12
NuGet\Install-Package Cocoar.FileSystem -Version 0.1.0-alpha.12
<PackageReference Include="Cocoar.FileSystem" Version="0.1.0-alpha.12" />
<PackageVersion Include="Cocoar.FileSystem" Version="0.1.0-alpha.12" />
<PackageReference Include="Cocoar.FileSystem" />
paket add Cocoar.FileSystem --version 0.1.0-alpha.12
#r "nuget: Cocoar.FileSystem, 0.1.0-alpha.12"
#:package Cocoar.FileSystem@0.1.0-alpha.12
#addin nuget:?package=Cocoar.FileSystem&version=0.1.0-alpha.12&prerelease
#tool nuget:?package=Cocoar.FileSystem&version=0.1.0-alpha.12&prerelease
Cocoar.FileSystem
Production-ready file system utilities for .NET with automatic error recovery and multi-platform support.
๐ Features
- ๐ก๏ธ Resilient File System Monitoring - Production-ready FileSystemWatcher with automatic fallback
- ๐ Auto-Recovery - Handles directory disappearing/reappearing, permission errors, watcher crashes
- โก Efficient & Reliable - Automatic switching between FileSystemWatcher (efficient) and polling (resilient)
- ๐ฏ Debouncing - Built-in debouncing to reduce noise from rapid file changes
- ๐ High-Performance File Search - Fast directory traversal with lazy evaluation
- ๐ Cross-Platform - Tested on Windows, Linux, and macOS
- ๐ฆ Zero Dependencies - Lightweight with no external dependencies
๐ฅ Installation
dotnet add package Cocoar.FileSystem
๐ Quick Start
Basic File Monitoring
using Cocoar.FileSystem;
var monitor = new ResilientFileSystemMonitor(new ResilientFileSystemMonitor.Options
{
Path = @"C:\configs",
Filter = "*.json",
EnablePollingFallback = true,
PollingInterval = TimeSpan.FromSeconds(5)
});
monitor.Changed += (sender, e) =>
{
Console.WriteLine($"File changed: {e.Name}");
ReloadConfiguration(e.FullPath);
};
monitor.Created += (sender, e) =>
{
Console.WriteLine($"File created: {e.Name}");
};
With Debouncing
var monitor = new ResilientFileSystemMonitor(new ResilientFileSystemMonitor.Options
{
Path = @"C:\data",
Filter = "*.txt",
EnablePollingFallback = true,
DebounceTime = TimeSpan.FromMilliseconds(500) // Only fire once per file per 500ms
});
monitor.Changed += (sender, e) =>
{
// This will only fire once even if file is saved multiple times rapidly
ProcessFile(e.FullPath);
};
Reactive Stream (ChannelReader)
For reactive scenarios, you can consume all events as a unified ordered stream:
var monitor = new ResilientFileSystemMonitor(new ResilientFileSystemMonitor.Options
{
Path = @"C:\data"
});
// Consume events from the channel - all events in order!
await foreach (var evt in monitor.Events.ReadAllAsync(cancellationToken))
{
switch (evt.Kind)
{
case FileSystemEventKind.Created:
Console.WriteLine($"Created: {evt.FullPath}");
break;
case FileSystemEventKind.Changed:
Console.WriteLine($"Changed: {evt.FullPath}");
break;
case FileSystemEventKind.Deleted:
Console.WriteLine($"Deleted: {evt.FullPath}");
break;
case FileSystemEventKind.Renamed:
Console.WriteLine($"Renamed: {evt.OldFullPath} โ {evt.FullPath}");
break;
case FileSystemEventKind.Error:
Console.WriteLine($"Error: {evt.Exception?.Message}");
break;
case FileSystemEventKind.ModeChanged:
Console.WriteLine($"Mode changed to {evt.Mode}: {evt.Reason}");
break;
}
}
Benefits:
- โ All events (Created, Changed, Deleted, Renamed, Error, ModeChanged) in one ordered stream
- โ No race conditions - events are guaranteed to be delivered in order
- โ Works perfectly with LINQ, Rx.NET, or async iteration
- โ
No need for
System.Reactivedependency
// Example: Throttle with LINQ
await foreach (var evt in monitor.Events.ReadAllAsync()
.Where(e => e.Kind == FileSystemEventKind.Changed)
.ToAsyncEnumerable())
{
// Process only change events
}
High-Performance File Search
using Cocoar.FileSystem;
// Simple search - all text files
var files = FileSearcher.EnumerateFiles(
new DirectoryInfo(@"C:\projects"),
"*.txt");
foreach (var file in files)
{
Console.WriteLine(file);
}
// With depth limit and excluded folders
var codeFiles = FileSearcher.EnumerateFiles(
new DirectoryInfo(@"C:\repos\myproject"),
"*.cs",
excludedFolders: new HashSet<string> { "bin", "obj", "node_modules", ".git" },
maxDepth: 5);
foreach (var file in codeFiles)
{
ProcessCodeFile(file);
}
// Lazy evaluation - efficient for large directory trees
var largeSearch = FileSearcher.EnumerateFiles(
new DirectoryInfo(@"C:\large-directory"),
"*");
// Only enumerates first 10 files
var firstTen = largeSearch.Take(10).ToList();
Monitor Mode Changes (Observability)
var monitor = new ResilientFileSystemMonitor(new ResilientFileSystemMonitor.Options
{
Path = @"C:\data",
EnablePollingFallback = true
});
monitor.ModeChanged += (sender, e) =>
{
Console.WriteLine($"Monitor switched to {e.NewMode}: {e.Reason}");
};
monitor.Error += (sender, e) =>
{
Console.WriteLine($"Monitor error: {e.GetException().Message}");
};
// Check current state
if (monitor.IsWatcherActive)
{
Console.WriteLine("Using efficient FileSystemWatcher");
}
else if (monitor.IsPolling)
{
Console.WriteLine("Using polling fallback");
}
๐ Documentation
- ResilientFileSystemMonitor Guide - Detailed usage guide
- Examples - More usage examples
๐ Key Benefits Over Raw FileSystemWatcher
- โ No crashes when directory doesn't exist initially
- โ No silent failures when watcher encounters errors
- โ Handles Docker volume mounts appearing after container start
- โ Handles network share availability issues
- โ Built-in debouncing (no need for manual throttling)
- โ Production-ready error handling
- โ Cross-platform compatibility
๐ ๏ธ Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
Path |
string |
(required) | Directory path to monitor |
Filter |
string |
"*" |
File filter pattern (e.g., ".json", ".txt") |
IncludeSubdirectories |
bool |
false |
Monitor subdirectories recursively |
NotifyFilter |
NotifyFilters |
LastWrite \| FileName \| CreationTime |
Types of changes to watch for |
EnablePollingFallback |
bool |
true |
Enable automatic polling fallback |
PollingInterval |
TimeSpan |
5 seconds |
How often to poll when in fallback mode |
AutoRecoverFromErrors |
bool |
true |
Automatically switch to polling on errors |
DebounceTime |
TimeSpan? |
null |
Optional debouncing to reduce event noise |
๐งต Thread Safety
All operations are thread-safe. Events are raised sequentially on a background thread, guaranteeing:
- โ Events are delivered in the order they occurred
- โ No concurrent event handler invocations (unless you subscribe multiple handlers)
- โ
When using the
Eventschannel, you have full control over concurrency
๐๏ธ Disposal
Always dispose when done:
using var monitor = new ResilientFileSystemMonitor(options);
// Use monitor...
// Automatically disposed at end of scope
๐ค Contributing & Versioning
- SemVer (additive MINOR, breaking MAJOR)
- PRs & issues welcome
- Licensed under Apache License 2.0 (explicit patent grant & attribution via NOTICE)
๐ License & Trademark
This project is licensed under the Apache License, Version 2.0. See NOTICE for attribution.
"Cocoar" and related marks are trademarks of COCOAR e.U. Use of the name in forks or derivatives should preserve attribution and avoid implying official endorsement. See TRADEMARKS for permitted and restricted uses.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Cocoar.FileSystem:
| Package | Downloads |
|---|---|
|
Cocoar.Configuration
Reactive, strongly-typed configuration layering for .NET with health monitoring, file resilience, and zero-downtime updates. Core library providing ConfigManager, providers (file, environment, command-line, observable), and differential updates. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.2.0 | 242 | 11/15/2025 |
| 2.1.0 | 543 | 11/13/2025 |
| 2.0.0 | 282 | 11/12/2025 |
| 1.0.0 | 209 | 11/5/2025 |
| 0.1.0-alpha.15 | 151 | 11/4/2025 |
| 0.1.0-alpha.14 | 144 | 11/4/2025 |
| 0.1.0-alpha.13 | 141 | 11/4/2025 |
| 0.1.0-alpha.12 | 143 | 11/4/2025 |
Full release notes: https://github.com/cocoar-dev/Cocoar.FileSystem/blob/develop/CHANGELOG.md