C# Overwriting file with StreamWriter created from FileStream

The problem you are having is that reading from the stream advances to the end of the file. Further writes will then append.

This will achieve a full overwrite.

using(FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
    StreamReader sr = new StreamReader(fs);
    using (StreamWriter sw = new StreamWriter(fs))
    {
        newString = someStringTransformation(sr.ReadToEnd());

        // discard the contents of the file by setting the length to 0
        fs.SetLength(0); 

        // write the new content
        sw.Write(newString);
    }
}

Why use SetLength? Your new content might be shorter than the existing string! The last thing you want is the old content at the end of your file.


There are several steps you need to take here but let me make my assumptions clear:

You need to keep the file open and locked during the entire operation to prevent others from accessing the file during this time.

With that said, here's what you need to do:

  1. You need to read the contents using the StreamReader, as you've done
  2. You need to reposition the underlying stream back to the start, its position have been changed by reading through the reader
  3. You need to write out the transformed contents through the StreamWriter, as you've done
  4. You need to flush the writer because of the next step
  5. You need to truncate the underlying stream/file to its current position, to handle a transformation that shortens the contents.

The code for all of this could look like this LINQPad program:

void Main()
{
    const string filePath = @"d:\temp\test.txt";
    var encoding = Encoding.UTF8;
    using (var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
    using (var reader = new StreamReader(stream, encoding))
    using (var writer = new StreamWriter(stream, encoding))
    {
        // Read
        var contents = reader.ReadToEnd();

        // Transform
        var transformedContents = contents.Substring(0, Math.Max(0, contents.Length - 1));

        // Write out transformed contents from the start of the file
        stream.Position = 0;
        writer.Write(transformedContents);
        writer.Flush();

        // Truncate
        stream.SetLength(stream.Position);
    }
}

Tags:

C#