user6767845
user6767845

Reputation:

Read and overwrite at the same FileStream

I'm using a FileStream to lock the File to be not writeable for other processes and also read and write to it, I'm using following method for it:

public static void ChangeOrAddLine(string newLine, string oldLine = "")
{
  string filePath = "C:\\test.txt";
  FileMode fm = FileMode.Create;
  //FileMode fm = FileMode.OpenOrCreate;
  using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
  using (StreamReader sr = new StreamReader(fs))
  using (StreamWriter sw = new StreamWriter(fs))
  {
    List<string> lines = sr.ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();
    bool lineFound = false;
    if (oldLine != "")
      for (int i = 0; i < lines.Count; i++)
        if (lines[i] == oldLine)
        {
          lines[i] = newLine;
          lineFound = true;
          break;
        }
    if (!lineFound)
      lines.Add(newLine);
    sw.Write(string.Join("\r\n", lines));
  }
}

I want to overwrite it with the new content but i don't find the right FileMode, using FileMode.OpenOrCreate just appends the new content to the old and FileMode.Create deletes the file-content at the time, the FileStream fm has been initialized, so the file is empty.

I need to just clear the old content at the moment, when i write the new content to it without losing the write-lock on it during the method is running.

Upvotes: 2

Views: 2305

Answers (1)

Henk Holterman
Henk Holterman

Reputation: 273844

OpenOrCreate just appends ...

Because you don't reposition after the reading.

That also shows the main problem with your approach: The FileStream only has one Position, and the Reader and the Writer heavily use caching.

However, as long as you want to replace everything and really need that locking scheme:

using (FileStream fs = new FileStream(filePath, 
        FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read))    
{    
    using (StreamReader sr = new StreamReader(fs))
    {
       ... // all the reading
    }
    fs.Position = 0; 
    using (StreamWriter sw = new StreamWriter(fs))
    {
        sw.Write(string.Join("\r\n", lines));
    }
    fs.SetLength(fs.Position); // untested, something along this line
}

and maybe you have to convince the sw and sr to leave their stream open.

But I have to note that the FileShare.Read flag doesn't make too much sense in this scenario. A reader could see al sorts of inconsistent data, including torn lines and broken UTF8 characters.

Upvotes: 4

Related Questions