First, it can be done. You can create the FileStream
with Read/Write access, and then write directly to the stream. Here is a proof of concept:
using (var v = new StreamWriter(File.Create("a.txt"))) {
v.WriteLine("1234A67890");
}
FileStream fs = new FileStream("a.txt", FileMode.Open, FileAccess.ReadWrite);
while (fs.ReadByte() != 'A') {} // Dangerous. Loops until 'A' found, infinite loop if none.
fs.Position--;
fs.WriteByte((byte)'5');
fs.Close(); // contents of a.txt now 1234567890
However, there are a number of fundamental problems with this approach:
- Risk of file corruption. If the program crashes (or there is a power outage, etc.), the file can be left in an inconsistent state.
- Inability to use
StreamReader
/StreamWriter
consistently. Both store data in an internal buffer, which can become stale if the underlying stream is being written to and read concurrently. You can call DiscardBufferedData
, but MSDN notes that "this method slows performance and should be called only when absolutely necessary."
- Complexity. Inserting text in-place within the file is a costly operation, requiring all subsequent data to be shifted in memory.
Instead, barring overwhelming considerations (e.g., the file is huge relative to available storage), you may want to consider this approach instead:
- Create a new temporary file. (You can use
System.IO.Path.GetTempFileName()
for this purpose).
- Read the existing file into the temporary file, making necessary changes. (Use
StreamReader
to read from the old file, and StreamWriter
to write to the new file.)
- Overwrite the existing file with the temporary file.
This approach is conceptually similar, but does not incur the risks and complexity of reading from and writing to the same stream concurrently.