Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileStream's FileMode.OpenOrCreate overwrites file

Documentation says FileMode.OpenOrCreate "specifies that the operating system should open a file if it exists; otherwise, a new file should be created", which sounds like it will open the file and write to it. Instead, the file seems to be overwritten.

How do I add to the file, rather than overwrite it?

class Logger : IDisposable
{
    private FileStream fs;
    private StreamWriter sw;
    
    public Logger()
    {
        // INTENT (but not reality): Will create file if one does not exist, otherwise opens existing file
        fs = new FileStream("log.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
        sw = new StreamWriter(fs, Encoding.UTF8);
    }

    public void Log(string message)
    {
        sw.WriteLine(message);
        sw.Flush();
        fs.Flush();
    }
    
    public void Dispose()
    {
        sw?.Dispose();
        fs?.Dispose();
    }
}
like image 574
Sinjai Avatar asked Jan 27 '23 13:01

Sinjai


1 Answers

The documentation is correct – but note that open and append are not synonymous.
FileMode.OpenOrCreate is not causing the FileStream constructor to delete the preexisting file wholesale; rather, it causes the stream to start at the beginning of the file. What you are observing is the file contents being overwritten by the StreamWriter, not the FileStream constructor replacing the file immediately.

You have to move the stream position to the end of the file to add text at the end. To do this, you could move the position with FileStream.Seek() or change the FileMode to FileMode.Append. FileMode.Append is likely more idiomatic but also requires making the FileAccess write-only, rather than read-write. Otherwise, an exception is thrown upon calling the contructor.

Option 1 (FileMode.OpenOrCreate, FileAccess.ReadWrite)

public Logger()
{
    // Will create file if one does not exist, otherwise opens existing file
    fs = new FileStream("log.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
    // Set stream position to end-of-file
    fs.Seek(0, SeekOrigin.End);
    sw = new StreamWriter(fs, Encoding.UTF8);
}

Option 2 (FileMode.Append, FileAccess.Write)

public Logger()
{
    // Will create file if one does not exist, otherwise appends to existing file
    fs = new FileStream("log.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
    sw = new StreamWriter(fs, Encoding.UTF8);
}
like image 159
Sinjai Avatar answered Feb 06 '23 13:02

Sinjai