9

对于使用文件作为公司设备预订的某种全局存储的应用程序,我需要一种读取和写入文件的方法(或锁定文件、读取文件、写入文件和解锁文件)。一个小代码片段将说明我的意思:

FileStream in = new FileStream("storage.bin", FileMode.Open);
//read the file
in.Close();

//!!!!!
//here is the critical section since between reading and writing, there shouldnt
//be a way for another process to access and lock the file, but there is the chance
//because the in stream is closed
//!!!!!
FileStream out = new FileStream("storage.bin", FileMode.Create);
//write data to file
out.Close();

这应该得到这样的东西

LockFile("storage.bin");
//read from it...
//OVERwrite it....
UnlockFile("storage.bin");

该方法应该是绝对安全的,因为程序应该同时在 2000 台设备上运行

4

5 回答 5

13

简单地保持FileStream具有独占(非共享)访问权限的打开将阻止其他进程访问该文件。这是打开文件进行读/写访问时的默认设置。

您可以通过截断它来“覆盖”您当前打开的文件。

所以:

using (var file = File.Open("storage.bin", FileMode.Open))
{
    // read from the file

    file.SetLength(0); // truncate the file

    // write to the file
}

该方法应该是绝对安全的,因为程序应该同时在 2000 台设备上运行

根据您写入文件的频率,这可能会成为一个瓶颈。您可能想对此进行测试以了解它的可扩展性。

此外,如果其中一个进程试图与另一个进程同时对文件进行操作,IOException则会抛出 an 。没有真正的“等待”文件的方法,因此您可能希望以更有序的方式协调文件访问。

于 2012-07-24T08:52:59.987 回答
3

您需要一个单独的流,为读取和写入而打开。

FileStream fileStream = new FileStream(
      @"c:\words.txt", FileMode.OpenOrCreate, 
      FileAccess.ReadWrite, FileShare.None);

或者你也可以试试

static void Main(string[] args)
    {
        var text = File.ReadAllText(@"C:\words.txt");
        File.WriteAllText(@"C:\words.txt", text + "DERP");
    }

根据http://msdn.microsoft.com/en-us/library/system.io.fileshare(v=vs.71).aspx

FileStream s2 = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.None);

您需要传入 None 的 FileShare 枚举值才能在 FileStream 构造函数重载上打开:

fs = new FileStream(@"C:\Users\Juan Luis\Desktop\corte.txt", FileMode.Open, 
    FileAccess.ReadWrite, FileShare.None);
于 2012-07-24T08:59:08.550 回答
2

我最终编写了这个助手类来做到这一点:

public static class FileHelper
{
    public static void ReplaceFileContents(string fileName, Func<String, string> replacementFunction)
    {
        using (FileStream fileStream = new FileStream(
                fileName, FileMode.OpenOrCreate,
                FileAccess.ReadWrite, FileShare.None))
        {
            StreamReader streamReader = new StreamReader(fileStream);
            string currentContents = streamReader.ReadToEnd();
            var newContents = replacementFunction(currentContents);
            fileStream.SetLength(0);
            StreamWriter writer = new StreamWriter(fileStream);
            writer.Write(newContents);
            writer.Close();
        }
    }
}

它允许您传递一个函数,该函数将获取现有内容并生成新内容,并确保在发生此更改时文件不会被其他任何内容读取或修改

于 2016-03-24T17:21:11.403 回答
1

我认为您只需要在重载的 Open 方法中使用FileShare.None标志。

file = File.Open("storage.bin", FileMode.Open, FileShare.None);
于 2012-07-24T09:03:12.727 回答
1

您可能正在寻找FileStream.LockFileStream.Unlock

于 2012-07-24T08:52:21.487 回答