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

发布于 2024-12-11 22:17:15 字数 624 浏览 0 评论 0原文

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

我尝试使用 FileStreamFileAccess.ReadWriteFileShare.Read 一起使用 Streamreader 进行读取,然后a StreamWriter (在同一个 FileStream 上)进行写入,但这会损坏文件。 FileAccessFileShare 的其他排列似乎也没有解决我的基本问题。

因此,我尝试在打开 StreamWriter 之前关闭 StreamReader,但这会更改 CanReadCanWrite 属性。 code>FileStream,所以我还是写不出来。

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

I need to be able to open a file to read it, maintaining a lock that denies other instances of the same application write access until I have written the amended file back to disk. The file is in a shared location on a network, and the app instances can be on any machine on the network.

I have tried using a FileStream with FileAccess.ReadWrite and FileShare.Read, with a Streamreader to read and then a StreamWriter (on the same FileStream) to write, but this corrupts the file. Other permutations of the FileAccess and FileShare don't seem to solve my basic problem either.

So I tried closing the StreamReader before opening the StreamWriter, but that changes the CanRead and CanWrite properties of the FileStream, so I still can't write.

Clearly I am taking the wrong approach, so can someone tell me how I should be approaching this? It seems a common enough thing to want to do - edit a file and block write access until the edited file is saved.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云朵有点甜 2024-12-18 22:17:15

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

解决方案可能是这样的:

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 在“需要的地方”锁定文件。

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

If you want to write to a file, you need to take exclusive file access, otherwise other programs can read partially written data (your writes aren't atomic). There are solutions to this, but they are quite complex.

A solution could be something like this:

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

where you always keep open the FileStream as

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

Before the data there is a "guard byte" that tells if the data is being written. If it's being written then reads on it will fail. The file is locked "where it's needed" using FileStream.Lock.

This clearly works better with binary fixed-length data. If you have variable length data (or you need to atomically update more "regions" of a file) then it becomes more complex. Normally you use DBs for this reason :-)

愚人国度 2024-12-18 22:17:15

使文件保持打开状态并具有写入权限。这应该会拒绝对该文件的所有其他写入。

Keep the file open with write access. That should deny all other writes to the file.

月依秋水 2024-12-18 22:17:15

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

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

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

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

As you don't specify what OS you're using nor whether access is time critical or order critical then I think that your best bet is to use a directory to indicate that the file is locked.

On most OS, creating a directory is pretty much instant, whereas creating a file isn't.
So each time your application wants access to the data file in question it must try and create a subdirectory in the same location as the file. If the directory already exists then the create will fail and your application must wait, trying again until it succeeds.

When it succeeds in creating the directory it can access the file and write it. Once all data has been written and file access closed then it should wait for a bit (to allow the actual write to complete) before deleting the directory.

You will, however, need to write some code that can handle an instance of your application crashing and leaving the lock directory present.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文