独家访问文本文件,读取和覆盖它

时间:2010-10-20 20:29:42

标签: vb.net file-io filestream streamreader streamwriter

我想打开一个文本文件,不允许任何其他进程写入它。我知道我可以使用以下FileStream执行此操作:

Dim fs As New FileStream(_FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read)

一旦我有这样的访问权限,我需要读取所有行(我将使用StreamReader(fs))然后我将需要写入文件(我将使用StreamWriter(fs))。

这里的问题是当我使用文件流作为参数而不是文件路径时,StreamWriter将不允许我将追加模式设置为false(因此我可以覆盖文件中的所有文本)。因此,使用StreamWriter编写的所有文本都会附加到我不想要的文本上。如果我使用带有文件路径的StreamWriter(可以让我设置追加为false)作为参数而不是文件流,它将因FileStream FileShare而被锁定。我怎样仍然可以独占访问该文件的读写,但仍能覆盖现有文本(追加模式为假)?

1 个答案:

答案 0 :(得分:1)

这并非不可能,您实际上并不需要使用Apppend = true初始化StreamWriter。您需要做的就是使用FileStream.Seek()来确保'文件指针'位于文件的末尾。这个示例C#代码运行良好:

using (var fs = new FileStream(@"c:\temp\test.txt", FileMode.Open,
        FileAccess.ReadWrite, FileShare.Read)) {
    var sr = new StreamReader(fs);   // NOTE: not using using
    string txt = sr.ReadToEnd();
    fs.Seek(0, SeekOrigin.End);      // Be sure
    var sw = new StreamWriter(fs);
    sw.WriteLine("appended");
    sw.Flush();
}

请注意此代码中的相当多的不适。我将从FileShare.Read开始,这是您的首选值。这意味着当你修补它时,你会让另一个进程读取文件。很有可能这个过程会对这个文件中显示的字节感到有点困惑,恕不另行通知。可以很好地运作,FileShare.None确保您的代码永远不会导致任何类型的事故。强烈推荐。

下一个标志是//注意不要使用。这很重要,因为StreamReader将对您传递的流的“责任”。如果在.NET代码中执行标准Right Thing,则当Using语句结束其范围时,该类将关闭流。这不是你想要的,你想保留文件,以便你可以写信给它。

Seek()调用执行StreamWriter构造函数的Append参数所做的操作,确保您要附加到文件而不是从头开始随机覆盖部分文件。由于您要追加,因此无需确保文件中的旧数据被截断。

Flush呼叫在这里有点臭。您来调用它来强制编写器刷新其输出缓冲区。如果不这样做,则文件中将丢失您所写内容的随机位。这通常不是问题,因为您调用Close()或使用Using语句来确保编写器已关闭。不是在这种情况下,FileStream正在调用镜头,它将在这里正确关闭文件,但它不知道另一个作者跳上了潮流并想写。

这会有效但却打破了相当数量的教条。更典型的模式是open-read + read + close,open-createnew + write + close。并且处理open-createnew可能失败的可能性,因为另一个进程抓住了该文件。多任务操作系统的危害总是准备好处理它。