Re: I/O buffering



On Wed, 04 Feb 2009 15:45:23 -0800, Michael D. Ober <obermd.@.alum.mit.edu.nospam.> wrote:

[...]
2)
a) StreamReader also buffers data?

b) I assume StreamWriter also buffers data internally, waiting for a
buffer to be full before it gets written to the underlying stream?

mdo> Both inherit from FileStream, so they buffer as well.

Neither StreamReader nor StreamWriter inherit from FileStream. They only even know about FileStream inasmuch as you can construct them using a string as input, in which case they implicitly create a FileStream on your behalf.

What StreamReader and StreamWriter _do_ use is any Stream instance. Not all Stream instances buffer, but for those that do (such as FileStream) there are two levels of buffering going on between the two classes. StreamReader and StreamWriter have their own buffers, and the underlying FileStream has its own buffer.

But, don't worry. That's not all the buffers that are involved. The OS has its own buffers, the disk controller has its own buffers, the disk itself has at least one layer of buffers, usually at least two.

Frankly, the only thing you really need to know about the buffering is that you need to call Flush(), Dispose(), or Close() to ensure data has finished being written when you're done.

3) But if both StreamWriter and FileReader already buffer data
internally, then why would we also need special classes for
buffering?

What's "FileReader"? Do you mean "StreamReader"?

Who says you "also need special classes for buffering"? FileStream just happens to use buffering as part of its normal operation, for efficiency reasons. You can actually disable the buffering if you really want to (specify an explicit buffer size of 0), but in any case, FileStream isn't a "special class for buffering", it's a special class for file i/o that just happens to have buffering.

mdo> All file streams are implemented in the FileStream class. The remaining stream classes that deal with files are simply wrappers for the FileStream class. This simplifies reading and writing files, especially text file.

I don't understand any of the above. If there are "remaining stream classes that deal with files", then how are those classes not "file streams"? And what does it mean for some "file stream" to be "implemented in the FileStream class"? What stream classes are you talking about that deal with files and which are simply wrappers for the FileStream class?

Note: the StreamReader and StreamWriter classes are not wrappers for the FileStream class. They wrap the Stream base class and are usable with any kind of Stream, not just those attached to a file.

4) I assume that if WriteStream ( or any other stream buffer ) object
buffers data, then data will only get written to a file when we either
call Flush(), Close() or when internal buffer is full?

mdo> Yes.

Dispose() should always flush the data. I don't know what "WriteStream" is, but assuming it's a typo for "StreamWriter", then disposing a StreamWriter will flush the StreamWriter buffers as well as the underlying Stream.

5)

a) Does OS( or its disk buffer) also buffer data from our streams?

mdo> Windows uses a write buffer for those disks that support it.

See above. There's all sorts of buffering going on.

b) If so, then I assume that calling Flush() from any of the I/O
objects ( FileStream or StreamWriter etc ) forces the underlying OS
buffer to flush its contets also?

mdo> I don't know about the net framework, but the underlying Win API defaults to not forcing a disk flush on file writes. You can open a file with a flag that instructs the Win API to not buffer file writes. I don't know if FileStream uses this flag or not.

My recollection is that .NET objects don't flush the lower-level OS objects. There's a limit to how far down they can force buffers to flush anyway, but if my memory serves me (and it sometimes doesn't :( ) calling FileStream's Flush() simply writes FileStream's own buffers out to the unmanaged OS object (file handle).

c) Is it possible that we would write some text to a disk ( via
StreamWriter class), but since we’d never call Flush() or Close() on
that stream, that this text would get buffered by a disk buffer, which
would only write it to a file at some later time ( perhaps when our
app has already stopped )?

No. Because the question is invalid, the answer must be "no". If you never call Flush() on FileStream (for example), the data that's still stuck in the FileStream's buffers would _not_ "get buffered by a disk buffer". It wouldn't get that far; that's the whole point of calling Flush(), to make sure it does get that far.

Now, if you _do_ call Flush(), there is in fact a possibility that the buffers from the OS object on (i.e. out of FileStream's control) wouldn't be written immediately and would be written at some later time, even after your application has stopped. But, keep in mind that at that level, the buffering is managed temporally as well as consumptively. That is, if data sits in a buffer for too long, it gets flushed whether or not the buffer fills up (is consumed).

[...]
6)

static void Main()
{
FileStream fs = new FileStream(@"D:\test.txt",
FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
StreamWriter sw1 = new StreamWriter(fs);


sw.Write("sw");
sw1.Write("sw1");

fs.Close();
sw.Close(); // exception
sw1.Close(); // exception
}

a) It seems that closing ‘fs’ doesn’t automatically close its wrapping
classes ‘sw’ and ‘sw1’ ( I’m assuming this because if ‘sw’ and ‘sw1’
were also closed, then the two would flush their buffered data to the
underlying stream )?

No, it doesn't. A Stream inside a StreamWriter knows nothing about the StreamWriter.

So how do we close ‘sw1’ and ‘sw’, if closing
them ( when we already closed underlying stream ) causes “cannot
access closed file” exception to be thrown?

You don't. It's a good reason not to have a given Stream attached to more than one StreamWriter at a time.

At best, you can call Flush() on both StreamWriter's, and then close them (catching and ignoring the exception on the second one you close).

We could, instead of
closing ‘fs’ directly, close one of its wrapper classes, say ‘sw’. But
we’d still need to somehow close ‘sw1’?!

Yes, you should (though in reality, probably not much harm would come from failing to). In reality, the answer is "don't do that". It's an ugly way to use StreamWriter. If you really must attach two StreamWriter's to the same FileStream, you should create an intermediary Stream sub-class that itself wraps FileStream, and which is used to create each StreamWriter, and which ignores the close/dispose from the StreamWriters (you would of course have to close the FileStream explicitly yourself, _after_ the StreamWriter's have been closed).

[...]
7) What does closing a stream mean? Just that OS releases the
resources previouslly occupied by a stream ( lock on files, etc )?

mdo> Yes.

Closing a Stream also flushes it, at least for explicit calls to Dispose() (the documentation warns that flushing may not be possible in a finalizer, due to the unpredictable ordering in which finalizers are called).

Pete
.



Relevant Pages

  • Re: FileStream.Flush not flushing?
    ... So when does the OS buffer get updated normally when using a ... FileStream? ... the file size is "correct" without closing the stream. ... >> As part of the application, I am writing information to file (that is, ...
    (microsoft.public.dotnet.framework.compactframework)
  • Re: Assembly conversion to Pocket Pc format
    ... But in my case it is throwing exception before executing that statement what ... That is before reading buffer size it is throwing ... Stream respStream = resp.GetResponseStream; ... upload and download files in compact framework. ...
    (microsoft.public.dotnet.framework.compactframework)
  • Re: scanf() quesion?
    ... characters are intended to ... When a stream is fully buffered, ... when a buffer is filled. ... If standard output refers to an interactive device, ...
    (comp.lang.c)
  • Re: I/O buffering
    ... classes (those with word Buffer in their name)? ... Stream class. ... One would not normally use BufferedStream with a FileStream, ... explicitly dispose your custom Stream class, when you were sure you were   ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: WMS source changing issue
    ... we use 5 second buffer in WMP. ... The question is - why the server is stopping broadcasting for a while (it ... clearly seen in network statistic in Task Manager) when switching to file ... We're streaming one 5Mbps live stream and one 5Mbps CBR file periodically so ...
    (microsoft.public.windowsmedia.server)

Loading