1

I am trying to use a text writer to write text to a file in .NET Core. The below code doesn't output anything to the file:

TextWriter writer = File.CreateText(@"...txt");
writer.Write("Hello World");

However, this does:

TextWriter writer = File.CreateText(@"...txt");
writer.Write("Hello World");
writer.Dispose();

Why is that? What does that extra line tell the program to do differently? I don't want to close the TextWriter because it is going to be writing logs, which are running constantly and indefinitely whilst my application is running.

How can I keep it open until the application stops running?

UPDATE

So the reason I want to do this, is I am using an SDK that writes its logs to a TextWriter:

TextWriterLogger(textWriter);
//Creates a logger that writes to a TextWriter. User is responsible for providing an instance of TextWriter that is thread safe.

But if I just enclose this in a using statement, logs won't be written because by the time they are ready to be written, the using statement will have executed and the TextWriter disposed.

Thanks

Harry Stuart
  • 1,781
  • 2
  • 24
  • 39
  • 1
    normally we open the file write and dispose and then reopen next time – Ehsan Sajjad Jan 03 '19 at 04:38
  • On some classes, however, it is possible to re-open an object which has been Close'd. Some such classes may keep some resources alive after a Close, in order to permit reopening; others may not keep any resources alive on Close, but might set a flag on Dispose to explicitly forbid re-opening. – Vishwa Ratna Jan 03 '19 at 04:43
  • You really shouldn't keep a file open like that throughout the lifetime of your app. You should do it something like this for a once of write: `using (TextWriter textWriter = File.AppendText(@"...txt")) TextWriterLogger(textWriter);`. If you're in a method that is writing many lines then keep the writer open for the duration of the method, but be careful of re-entrancy issues. – Enigmativity Jan 03 '19 at 04:52
  • The issue is, my code is not controlling when a log is written to the file so it's hard to wrap in a using statement. I am using TheGeneral's approach of just auto flushing. Is there anyway I can automatically dispose then instantiate once text has completed being written. – Harry Stuart Jan 03 '19 at 04:56

1 Answers1

5

Dispose calls Flush, which writes the internal bytes stored in a buffer to disk

Without closing or disposing a file, you are leaving unmanaged resources around and will potentially lock the file, not to mention memory leaks. Instead always use a using statement

using (TextWriter writer = File.CreateText(@"...txt"))
{
   writer.Write("Hello World");
}

However if you want to continually write to the file, you will have to flush it

FileStream.Flush Method

Clears buffers for this stream and causes any buffered data to be written to the file.

TextWriter writer = File.CreateText(@"...txt");
...
writer.Write("Hello World");
...
writer.Flush(); // at this point the bytes are flushed to disk
...
...
writer.Dispose();

In short most streams are backed by an internal array (buffer), so you dont thrash writes. The Default size is 4k, when it hits the buffer size then it automatically flushes. If you want to see immediate writes, the you have to flush it every time

Lastly some streams have an auto flush feature, which can do this job for you

AutoFlush

Gets or sets a value indicating whether the StreamWriter will flush its buffer to the underlying stream after every call to Write(Char)

When you are finished with the stream always dispose it

TheGeneral
  • 79,002
  • 9
  • 103
  • 141