锁定文件以进行写入/删除,同时允许任何进程读取

问题描述 投票:0回答:5

我正在用 C# (.NET) 开发一个应用程序,在处理文件锁定时遇到问题。

  • 我的主应用程序 (A) 需要对某个文件进行读/写访问。
  • 单独的应用程序 (B) 需要对同一文件进行读取访问。
  • 我需要防止用户在我的应用程序 (A) 运行时编辑或删除文件。应用程序 (A) 长时间运行。 (A) 运行时不得删除该文件,即使没有主动读取或写入该文件。

我完全控制了(A)和(B)的来源,所以我可以修改它们中的任何一个。

如何在应用程序 (A) 运行时阻止用户修改/删除文件,同时允许应用程序 (A) 读/写和应用程序 (B) 读?

c# .net file-io
5个回答
24
投票

使用

FileShare.Read
仅允许从其他应用程序读取。您可以通过在应用程序 A 运行时打开流来锁定文件。您需要一个
NonClosingStreamWrapper
以避免在处置
StreamWriter
时处置流(这会通过
using
自动发生)

NonClosingStreamWrapper
,作者:Jon Skeet,可以从这里

找到

示例

当应用程序启动时使用它来锁定文件

FileStream fileStream = new FileStream(file, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);

写入文件时使用

using (StreamWriter sr = new StreamWriter(new NonClosingStreamWrapper(fileStream)))
{
    // File writing as usual
}

当应用程序结束时使用它来释放文件

fileStream.Close();

2
投票

大多数时候,锁定文件并不是为了防止用户删除文件,而是通知运行应用程序另一个实例的用户该文件正在被另一个用户“使用”。如果多个用户在共享文件夹中打开/写入文件,则此功能特别有用。 在这种情况下,使用应用程序 (A) 打开文件时生成的“锁定文件”会更容易,而不是在文件系统级别锁定文件。因此,任何其他应用程序都会注意到锁定文件的存在(您可以使用相同的文件名但不同的扩展名来命名它),并且在锁定文件内您可以写入谁以及何时有人获取了锁。应用程序 (B) 现在可以响应用户...“该文件似乎正在由计算机 yyy 上的用户 xxx 修改,您真的要加载它吗?”

当然,当应用程序文件不再使用或应用程序终止时,应用程序必须删除锁定文件。在“不幸”的情况下,崩溃会在文件系统上留下锁定,用户只需对警告请求响应“是”,或者可以手动删除它以释放锁定。

希望这有帮助,

保罗·马拉尼


0
投票

如果您只想锁定文件,以防止写入或删除,但不想更改文件。

我用它来锁定稍后使用的zip文件,这样其他人就可以读取它,但不能更改或更改。 如果我使用@Cloudanger的答案,我将无法再在其他进程中读取zip文件。

FileStream fileStreamSslFile = new FileStream(zipFile, FileMode.OpenOrCreate, 
FileAccess.Read, FileShare.Read);

0
投票

自从

.NET Framework 4.5.1
以来,
StreamWriter
有了一个构造函数
,即使在
Stream
对象已被处置之后,也可以保持底层
StreamWriter
打开

// Open the FileStream at the start of the program
FileStream fileStream = new FileStream(
    "file.json",
    FileMode.OpenOrCreate,
    FileAccess.ReadWrite,
    FileShare.Read
);

try
{
    // Perform operations

    // Reset the position of the FileStream to the beginning
    fileStream.Seek(0, SeekOrigin.Begin);

    using (StreamWriter writer = new StreamWriter(fileStream, Encoding.UTF8, leaveOpen: true))
    {
        // Write to the StreamWriter as usual
        writer.Write("...");
    }

    // Perform more operations

    // Reset the position of the FileStream to the beginning
    fileStream.Seek(0, SeekOrigin.Begin);

    using (StreamWriter writer = new StreamWriter(fileStream, Encoding.UTF8, leaveOpen: true))
    {
        // Write to the StreamWriter as usual
        writer.Write("...");
    }
}
finally
{
    // Manually dispose of the FileStream at the end of the program
    fileStream.Dispose();
}

或者,如果您有想要写入的

byte
,您可以直接写入
FileStream
:

// Open the FileStream at the start of the program
FileStream fileStream = new FileStream(
    "file.json",
    FileMode.OpenOrCreate,
    FileAccess.ReadWrite,
    FileShare.Read
);

try
{
    // Perform operations

    // Reset the position of the FileStream to the beginning
    fileStream.Seek(0, SeekOrigin.Begin);

    // Get bytes that need to be written to the file
    byte[] bytes = Array.Empty<byte>();

    fileStream.Write(bytes);
    fileStream.Flush();

    // Perform more operations
}
finally
{
    // Manually dispose of the FileStream at the end of the program
    fileStream.Dispose();
}

-1
投票

虽然我没有使用过它,但是命名为

Mutex
可以拯救你的一天。在应用程序 A 中打开文件之前,创建一个互斥体,如下所示:

Mutex(bool initiallyOwned, string name, out bool createdNew)

将文件名作为第二个参数传递。

现在,当您在应用程序 B 中打开文件时,再次使用

Mutex
如果
out
参数
createdNew
为 false,则文件已被 A 打开,因此您只能读取它。

© www.soinside.com 2019 - 2024. All rights reserved.