文件锁定 - 读取然后锁定时写入

时间:2011-10-27 09:36:49

标签: c# file-io locking

我需要能够打开一个文件来读取它,维护一个锁定,拒绝同一个应用程序写入访问的其他实例,直到我将修改后的文件写回磁盘。该文件位于网络上的共享位置,应用程序实例可以位于网络上的任何计算机上。

我尝试使用FileStreamFileAccess.ReadWriteFileShare.ReadStreamreader阅读,然后StreamWriter(同一FileStream写入,但这会破坏文件。 FileAccessFileShare的其他排列似乎也无法解决我的基本问题。

所以我在打开StreamReader之前尝试关闭StreamWriter,但这会更改CanRead的{​​{1}}和CanWrite属性,所以我仍然可以不写。

显然我采取了错误的方法,所以有人能告诉我应该如何接近这个吗?这似乎是一件很常见的事情 - 编辑文件并阻止写入访问,直到保存编辑过的文件。

3 个答案:

答案 0 :(得分:0)

如果要写入文件,则需要进行独占文件访问,否则其他程序可以读取部分写入的数据(您的写入不是原子的)。有解决方案,但它们非常复杂。

解决方案可能是这样的:

static bool Read(FileStream fs, byte[] data, long position)
{
    fs.Seek(position, SeekOrigin.Begin);

    if (fs.ReadByte() == 0)
    {
        // Block of data not finished writing
        return false;
    }

    fs.Read(data, 0, data.Length);
    return true;
}

static bool Write(FileStream fs, byte[] data, long position)
{
    try
    {
        fs.Lock(position, data.Length + 1);
        fs.Seek(position, SeekOrigin.Begin);
        fs.WriteByte(0);
        fs.Write(data, 0, data.Length);
        fs.Seek(position, SeekOrigin.Begin);
        fs.WriteByte(1);
        fs.Unlock(position, data.Length + 1);
        return true;
    }
    catch (IOException)
    {
        return false;
    }
}

static bool Append(FileStream fs, byte[] data)
{
    return Write(fs, data, fs.Length);
}

您始终将FileStream打开为

FileStream fs1 = new FileStream("Test.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);

data之前有一个“保护字节”,告诉我们是否正在写入数据。如果它正在写入,则读取它将失败。使用FileStream.Lock将文件锁定在“需要的位置”。

这对二进制固定长度数据显然更有效。如果您有可变长度的数据(或者您需要以原子方式更新文件的更多“区域”),那么它就会变得更加复杂。通常,您出于以下原因使用DB: - )

答案 1 :(得分:0)

使用写访问权限保持文件打开。这应该拒绝对文件的所有其他写入。

答案 2 :(得分:0)

由于您没有指定您正在使用的操作系统,也没有指定访问是时间关键或命令关键,因此我认为您最好的选择是使用目录来指示文件已被锁定。

在大多数操作系统上,创建目录几乎是即时的,而创建文件却不是。 因此,每次您的应用程序想要访问有问题的数据文件时,它必须尝试在与文件相同的位置创建一个子目录。如果该目录已存在,则创建将失败,您的应用程序必须等待,再次尝试直到成功。

当它成功创建目录时,它可以访问该文件并进行编写。一旦所有数据都被写入并且文件访问被关闭,那么在删除目录之前它应该等待一点(以允许实际写入完成)。

但是,您需要编写一些代码来处理应用程序崩溃的实例并保留锁定目录。