Cocoar.FileSystem 0.1.0-alpha.13

This is a prerelease version of Cocoar.FileSystem.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Cocoar.FileSystem --version 0.1.0-alpha.13
                    
NuGet\Install-Package Cocoar.FileSystem -Version 0.1.0-alpha.13
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cocoar.FileSystem" Version="0.1.0-alpha.13" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cocoar.FileSystem" Version="0.1.0-alpha.13" />
                    
Directory.Packages.props
<PackageReference Include="Cocoar.FileSystem" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cocoar.FileSystem --version 0.1.0-alpha.13
                    
#r "nuget: Cocoar.FileSystem, 0.1.0-alpha.13"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Cocoar.FileSystem@0.1.0-alpha.13
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cocoar.FileSystem&version=0.1.0-alpha.13&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Cocoar.FileSystem&version=0.1.0-alpha.13&prerelease
                    
Install as a Cake Tool

Cocoar.FileSystem

NuGet License .NET

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 (Fluent API)

using Cocoar.FileSystem;

// Simple, clean fluent API
var monitor = ResilientFileSystemMonitor
    .Watch(@"C:\configs", "*.json")
    .OnChanged((sender, e) => 
    {
        Console.WriteLine($"File changed: {e.Name}");
        ReloadConfiguration(e.FullPath);
    })
    .OnCreated((sender, e) => 
    {
        Console.WriteLine($"File created: {e.Name}");
    })
    .OnRenamed((sender, e) => 
    {
        Console.WriteLine($"File renamed: {e.OldName} โ†’ {e.Name}");
    })
    .Build();

With Debouncing

var monitor = ResilientFileSystemMonitor
    .Watch(@"C:\data", "*.txt")
    .WithDebounce(500) // milliseconds - only fire once per file per 500ms
    .OnChanged((sender, e) => 
    {
        // This will only fire once even if file is saved multiple times rapidly
        ProcessFile(e.FullPath);
    })
    .Build();

Options Pattern (Alternative)

You can still use the options pattern for configuration or serialization scenarios:

var monitor = new ResilientFileSystemMonitor(new ResilientFileSystemMonitor.Options
{
    Path = @"C:\configs",
    Filter = "*.json",
    EnablePollingFallback = true,
    PollingInterval = TimeSpan.FromSeconds(5),
    DebounceTime = TimeSpan.FromMilliseconds(500)
});

monitor.Changed += (sender, e) => ReloadConfiguration(e.FullPath);

Reactive Stream (ChannelReader)

For reactive scenarios, you can consume all events as a unified ordered stream:

var monitor = ResilientFileSystemMonitor
    .Watch(@"C:\data")
    .Build();

// 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.Reactive dependency
// 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 (Fluent API)

using Cocoar.FileSystem;

// Simple search - all text files
var files = FileSearcher
    .Search(@"C:\projects", "*.txt")
    .ToList();

foreach (var file in files)
{
    Console.WriteLine(file);
}

// With depth limit and excluded folders
var codeFiles = FileSearcher
    .Search(@"C:\repos\myproject", "*.cs")
    .Excluding("bin", "obj", "node_modules", ".git")
    .WithMaxDepth(5)
    .ToList();

foreach (var file in codeFiles)
{
    ProcessCodeFile(file);
}

// Lazy evaluation - efficient for large directory trees
var firstTen = FileSearcher
    .InDirectory(@"C:\large-directory")
    .Take(10)
    .ToList();

// Current directory only (no recursion)
var localFiles = FileSearcher
    .Search(@"C:\temp", "*.log")
    .InCurrentDirectoryOnly()
    .ToArray();

// Check if any files exist
bool hasConfig = FileSearcher
    .Search(@"C:\config", "*.json")
    .Any();

Direct API (Alternative)

You can also use the direct API for more control:

// Simple search - all text files
var files = FileSearcher.EnumerateFiles(
    new DirectoryInfo(@"C:\projects"),
    "*.txt");

// 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);

Monitor Mode Changes (Observability)

var monitor = ResilientFileSystemMonitor
    .Watch(@"C:\data")
    .OnModeChanged((sender, e) => 
    {
        Console.WriteLine($"Monitor switched to {e.NewMode}: {e.Reason}");
    })
    .OnError((sender, e) => 
    {
        Console.WriteLine($"Monitor error: {e.GetException().Message}");
    })
    .Build();

// Check current state
if (monitor.IsUsingWatcher)
{
    Console.WriteLine("Using efficient FileSystemWatcher");
}
else
{
    Console.WriteLine("Using polling fallback");
}

๐Ÿ“š Documentation

๐Ÿ”‘ 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 Events channel, you have full control over concurrency

๐Ÿ—‘๏ธ Disposal

Always dispose when done:

using var monitor = ResilientFileSystemMonitor
    .Watch(@"C:\data")
    .Build();
// 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • 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 186 11/15/2025
2.1.0 529 11/13/2025
2.0.0 270 11/12/2025
1.0.0 197 11/5/2025
0.1.0-alpha.15 138 11/4/2025
0.1.0-alpha.14 131 11/4/2025
0.1.0-alpha.13 131 11/4/2025
0.1.0-alpha.12 135 11/4/2025