ZetCode

C# FileShare 枚举

最后修改于 2025 年 4 月 20 日

本教程解释了如何在 C# 中使用 FileShare 枚举来控制打开文件时的文件共享行为。FileShare 决定了其他进程如何访问同一文件。

FileShare 枚举指定了其他流可以对同一文件拥有的访问级别。 它在使用 FileStream 或类似类打开文件时使用。

FileShare 对于多进程文件访问场景至关重要。 它有助于防止文件访问冲突并实现受控共享。

基本 FileShare 示例

此示例演示了如何使用 FileShare.None 来阻止在文件打开时对文件的任何其他访问。 这是最严格的模式。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "test.txt";
        
        try
        {
            // Open file with exclusive access
            using (var fs = new FileStream(filePath, 
                   FileMode.OpenOrCreate, 
                   FileAccess.ReadWrite, 
                   FileShare.None))
            {
                Console.WriteLine("File opened exclusively. Try opening in another process.");
                Console.ReadLine();
            }
        }
        catch (IOException ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

当使用 FileShare.None 时,任何其他进程尝试打开该文件都会失败,直到第一个进程关闭它。 此示例创建一个具有 FileShare.None 的 FileStream,这意味着没有其他进程可以在文件打开时访问该文件。

如果在此代码运行时尝试在另一个程序中打开该文件,您将收到访问被拒绝的错误。 这演示了如何在敏感操作期间完全锁定文件。 using 语句确保在完成后正确关闭文件。

FileShare.Read 示例

此示例展示了如何在您打开文件时允许其他进程读取该文件。 FileShare.Read 允许并发读取访问。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "shared.txt";
        File.WriteAllText(filePath, "Sample content");
        
        // Open file allowing others to read it
        using (var fs = new FileStream(filePath, 
               FileMode.Open, 
               FileAccess.ReadWrite, 
               FileShare.Read))
        {
            Console.WriteLine("File opened with FileShare.Read");
            Console.WriteLine("Other processes can read this file now");
            Console.ReadLine();
        }
    }
}

FileShare.Read 允许其他进程打开文件进行读取,但不允许写入。 在此示例中,文件使用 FileShare.Read 打开,这意味着其他进程可以同时打开文件进行读取,但不能修改它。

当您需要确保数据一致性,同时允许其他应用程序进行只读访问时,这非常有用。 该文件将保持锁定状态以进行写入,直到原始进程关闭它。 这种模式在允许多个读取器存在的读取密集型场景中很常见。

FileShare.Write 示例

此示例演示了 FileShare.Write,它允许其他进程在您打开文件时写入该文件。 请谨慎使用。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "writable.txt";
        File.WriteAllText(filePath, "Initial content");
        
        // Open file allowing others to write to it
        using (var fs = new FileStream(filePath, 
               FileMode.Open, 
               FileAccess.Read, 
               FileShare.Write))
        {
            Console.WriteLine("File opened with FileShare.Write");
            Console.WriteLine("Other processes can write to this file now");
            
            // Read and display initial content
            using (var reader = new StreamReader(fs))
            {
                Console.WriteLine($"Current content: {reader.ReadToEnd()}");
            }
            
            Console.ReadLine();
        }
    }
}

FileShare.Write 允许其他进程在您打开文件时写入该文件。 此示例使用 FileShare.Write 打开文件,允许其他进程并发修改该文件。

请注意,我们只读取文件 (FileAccess.Read),同时允许其他人写入。 如果管理不当,这可能会导致竞争条件。 该示例显示了初始内容,但如果另一个进程写入该文件,则可能会更改。 这种模式在特定场景(例如日志文件监控)中非常有用。

FileShare.ReadWrite 示例

此示例显示 FileShare.ReadWrite,它允许其他进程进行读取和写入。 这是最宽松的共享模式。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "shared_rw.txt";
        File.WriteAllText(filePath, "Initial content");
        
        // Open file allowing full shared access
        using (var fs = new FileStream(filePath, 
               FileMode.Open, 
               FileAccess.ReadWrite, 
               FileShare.ReadWrite))
        {
            Console.WriteLine("File opened with FileShare.ReadWrite");
            Console.WriteLine("Others can both read and write this file");
            
            // Demonstrate writing
            using (var writer = new StreamWriter(fs))
            {
                writer.WriteLine("New content added");
                writer.Flush();
            }
            
            Console.ReadLine();
        }
    }
}

FileShare.ReadWrite 允许对文件进行完全共享访问。 此示例演示了打开一个启用完全共享的文件,这意味着其他进程可以同时读取和写入该文件。

该代码将新内容写入文件,同时允许其他进程执行相同操作。 此模式需要进程之间进行仔细协调以避免数据损坏。 它通常用于多个进程需要使用适当的同步在同一文件上进行协作的场景中。

FileShare.Delete 示例

此示例演示了 FileShare.Delete,它允许其他进程在您打开文件时删除该文件。 实际上,只有在关闭所有句柄后才会删除该文件。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "deletable.txt";
        File.WriteAllText(filePath, "Sample content");
        
        // Open file allowing delete operation
        using (var fs = new FileStream(filePath, 
               FileMode.Open, 
               FileAccess.Read, 
               FileShare.Delete))
        {
            Console.WriteLine("File opened with FileShare.Delete");
            Console.WriteLine("Try deleting this file in Explorer");
            Console.ReadLine();
            
            // Check if file still exists
            Console.WriteLine($"File exists after sharing for delete: {File.Exists(filePath)}");
        }
        
        // Now check if file was actually deleted
        Console.WriteLine($"File exists after closing: {File.Exists(filePath)}");
    }
}

FileShare.Delete 允许在打开文件时将其标记为删除。 在此示例中,文件使用 FileShare.Delete 打开,这意味着另一个进程可以请求删除它。

实际删除仅在所有文件句柄都关闭时才会发生。 该示例通过在不同阶段检查 File.Exists 来演示这一点。 这对于临时文件或在需要新版本替换现有版本的文件替换模式中非常有用。

组合 FileShare 标志示例

FileShare 标志可以使用按位 OR 组合。 此示例展示了如何同时允许读取和删除。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "combo.txt";
        File.WriteAllText(filePath, "Combined sharing example");
        
        // Combine Read and Delete sharing modes
        using (var fs = new FileStream(filePath, 
               FileMode.Open, 
               FileAccess.ReadWrite, 
               FileShare.Read | FileShare.Delete))
        {
            Console.WriteLine("File opened with Read + Delete sharing");
            Console.WriteLine("Others can read or delete this file");
            
            // Write some data
            using (var writer = new StreamWriter(fs))
            {
                writer.WriteLine("Additional content");
                writer.Flush();
            }
            
            Console.ReadLine();
        }
    }
}

FileShare 标志是可以组合的位标志。 此示例结合了 FileShare.Read 和 FileShare.Delete 以同时允许这两种操作。 其他进程可以读取该文件,也可以将其标记为删除。

当您希望允许读者同时允许清理操作时,此组合非常有用。 按位 OR 运算符 (|) 组合这些标志。 可以通过这种方式组合多个标志,从而为不同的用例创建精确的共享行为。

真实世界的 FileShare 场景

此示例演示了在日志记录系统中 FileShare 的实际应用,其中多个进程可能需要写入同一个日志文件。

Program.cs
using System;
using System.IO;
using System.Threading;

class Program
{
    static void Main()
    {
        string logPath = "application.log";
        
        // Simulate multiple processes writing to log
        for (int i = 0; i < 3; i++)
        {
            new Thread(() =>  WriteToLog(logPath, $"Process {Thread.CurrentThread.ManagedThreadId}")).Start();
        }
        
        Thread.Sleep(3000); // Let threads work
        Console.WriteLine("Log content:");
        Console.WriteLine(File.ReadAllText(logPath));
    }
    
    static void WriteToLog(string path, string processName)
    {
        for (int i = 0; i < 5; i++)
        {
            try
            {
                // Allow read and write sharing
                using (var fs = new FileStream(path, 
                       FileMode.Append, 
                       FileAccess.Write, 
                       FileShare.ReadWrite))
                using (var writer = new StreamWriter(fs))
                {
                    writer.WriteLine($"{DateTime.Now}: {processName} - Message {i}");
                    writer.Flush();
                    Thread.Sleep(100); // Simulate work
                }
            }
            catch (IOException ex)
            {
                Console.WriteLine($"{processName} error: {ex.Message}");
            }
        }
    }
}

此示例模拟多个进程写入共享日志文件。 FileShare.ReadWrite 允许并发访问,而 FileMode.Append 确保线程安全追加。 每个“进程”(由线程模拟)将带有时间戳的几条消息写入日志文件。

FileShare.ReadWrite 模式允许其他进程读取和写入该文件,而 FileMode.Append 会自动查找文件末尾以进行写入。 这种组合通常用于日志记录系统,其中多个进程需要记录到同一个文件而不损坏数据。 该示例包括针对 IO 异常的基本错误处理。

来源

FileShare 枚举文档

本教程介绍了如何在 C# 中使用 FileShare 枚举来控制文件共享行为,示例范围从独占访问到复杂的共享场景。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。 我从 2007 年开始撰写编程文章。到目前为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我在编程教学方面拥有超过十年的经验。

列出所有 C# 教程