Which stream do I close when I do stream composition? - c#

If I have the following code:
FileStream fs = new FileStream(...);
TextWriter tw = new StreamWriter(fs);
Am I supposed to call only tw.Close(), or fs.Close() as well? I'm using the TextWriter persistently throughout an application, so I can't just wrap it in a Using(...) block, since I need to be able to use it at multiple points.
Otherwise, I would just write it as:
using (FileStream fs = new FileStream(...))
{
using (TextWriter tw = new StreamWriter(fs))
{
// do stuff
}
}
And avoid the issue at all together. But, I don't really know what to do in this circumstance. Do I close tw, fs, or both?
Also, more generally: If I compose multiple streams together, such as C(B(A)), can I call Close / Dispose on C and then not worry about having to call it on B and A?

You only need to close the StreamWriter.
From the documentation of the StreamWriter.Close method:
Closes the current StreamWriter object
and the underlying stream.
Also notable in the documentation of the method:
This implementation of Close calls the
Dispose method passing a true value.
This means that closing and disposing the StreamWriter are equivalent. You don't have to dispose the object after closing it, or close it before disposing it. The FileStream.Close method does the same, so closing or disposing the StreamWriter will also dispose the stream.
If you wouldn't be able to find information like this for a class, you can always dispose both the writer and the stream to be safe. Disposing an object that has already been disposed does not cause any problem, and the method would just do nothing. Just make sure to close them in the right order, i.e. closing the writer before the stream.

Because you have already enclosed your stream declaration in a "using" statement you to not need to specifically do either. Using invokes dispose and the dispose invokes close.
See this article from SO

You're safe to Dispose() both tw and fs. If tw does happen to Dispose() the underlying stream, calling Dispose() again will be a no-op.
Update: Now I see the real question... In your case, I would turn to ILSpy which shows that TextWriter.Dispose() does indeed call Close() on the underlying stream. So you're fine to just call tw.Dispose().

Related

Does flushing a a top level stream end up flushing all nested streams that the top level stream implicitly wraps? [duplicate]

I have a StreamWriter which underlying stream is a FileStream. Will the following code guarantee that the FileStream also flushes its buffer into the actual file on the file system, or do I need to explicitly call Flush() on the FileStream?
using (var fs = new FileStream("blabla", FileMode.Append)) {
using (var sw = new StreamWriter(fs)) {
sw.WriteLine("Hello, I want to be flushed.");
sw.Flush(); //I need this to also flush onto the file, not just to the FileStream
}
}
As per MSDN, "Flushing the stream will not flush its underlying encoder unless you explicitly call Flush or Close", but I do not know if a FileStream can be considered an "underlying encoder".
Also, if I don't specify FileOptions.WriteThrough, am I guaranteed that the OS will eventually write the flushed line onto the disk even if the program crashes before the two streams have been closed (assuming for example no using {} blocks, only a call to Flush())?
In my scenario I need to leave the stream open (for logging) so I cannot use using {} blocks, but I would like to make sure data will always be written to the disk even if the program crashes. I can afford to lose data if there is a power shutdown and the OS has not flushed onto the disk, but otherwise I need the OS to eventually flush even if I never properly call Close() on the stream.
Yes, calling Flush on StreamWriter will cause the underlying stream to be Flushed. The 4.5 version calls a private Flush(bool,bool) function, which ends with:
if (flushStream)
{
this.stream.Flush();
}
Where flushStream is the first parameter, this.stream is the stream that the StreamWriter was constructed on, and the call in Flush() is Flush(true,true).
(Older parts of answer - I was being very roundabout in answering. Moved most relevant part of answer to top)
It's not explicitly spelled out in the documentation anywhere I can find it, but any stream class that is constructed by passing it another stream should be assumed to "take ownership" of that stream (unless it's specifically called out otherwise).
That is, once you've constructed the StreamWriter using fs, you shouldn't perform any direct actions on fs yourself.
The part you quoted from MSDN relates to the later sentences:
This allows the encoder to keep its state (partial characters) so that it can encode the next block of characters correctly. This scenario affects UTF8 and UTF7 where certain characters can only be encoded after the encoder receives the adjacent character or characters.
That is, you may have passed data to Write such that you've given it some Unicode surrogates, but not a complete character. Flush will not write those surrogates to the stream. So long as you're always passing well formed (complete) strings to Write, you do not need to concern yourself about this.
Streams disposal is guaranteed if used with using block!
With a chain of streams,closing the outermost stream(at the head of the chain) i.e StreamWriter in your case closes the whole lot i.e FileStream
Flush method forces internal buffer to be written immediately.Flush is automatically called when stream is closed,so you never need to do the following
s.Flush();s.Close();
So,the moment the most topmost stream is closed it flushes and then closes it underlying streams who also flush there content.
For example consider this chain
FileStream->GZipStream->StreamWriter
So,the moment you close the StreamWriter
StreamWriter flushes and closes.It also closes undelying GZipStream
GzipStream flushes and closes.It also closes underlying FileStream
FileStream flushes and closes

"using" statment inside method can cause troubles of data corruption or Access violation?

I have a task, that set data into a FIFO, then another thread read this data inside the FIFO one by one and send it via network later. The data converted to byte array when call FIFO.Add, as following:
public byte[] ByteArraySerialize()
{
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
}
return m.ToArray();
}
}
My question: Is it possible that the data will be corrupted or disposed before the sender thread reads it from FIFO? My question is to understand using inside method:
Is this the way of using the using inside a method may cause GC to remove the MemoryStream, before the thread reads the data lets say after few second or minutes after this data entered the FIFO?
There are multiple ways to read this question but let's start with the obvious way, the way it was written:
Is this way of using the "using" inside a method may cause GC to remove the Memory Stream, before the thread read the data lets say after few second or minutest after this data enter the FIFO?
No. This will not be a problem. If you are able to read the data as part of the call to .ToArray(), then you already have a copy of the data. If GC later on collects the stream, the array will live on. To be clear, in relation to GC, if you can read a good copy of the internals of the stream at the point where you call .ToArray(), then that array will be OK afterwards. As per the documentation, you're getting a copy of the internal data, not a reference to it, and even so, if you have a reference to some internal data structure, GC will not be able to collect it.
However, another interpretation could be this: Is there something wrong with this code?
And well, yes, and no.
The current implementation of BinaryWriter will dispose of the underlying stream when the writer instance is disposed of. This means that the MemoryStream will be disposed of.
Let me copy your code and add some comments:
public byte[] ByteArraySerialize()
{
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
}
// m is really disposed here
return m.ToArray();
}
}
Does this make a difference? Well, no. In the current implementation, disposing of the memory stream will not in any way trash it. But there is nothing guaranteed about the current implementation or its future, this is undocumented behavior. If you want this code to be stable and trustworthy for future versions or hotfixes to .NET, I would not write it like this.
As such, I would not use this way of doing it. I would rewrite the code as follows:
using (MemoryStream m = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
writer.Flush();
return m.ToArray();
}
This will ask the writer to flush all the data, and then you make a copy of the internal array of the memory stream, before that instance is disposed.
Either that, or use the overloaded constructor and ask the writer to leave the stream open:
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m, Encoding.UTF8, true))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
}
// m is no longer disposed here
return m.ToArray();
}
The call to ToArray(); effectively makes a copy of the data you want.
So everything and anything happening to the MemStreams is irrelevant.
More generally, as long as your code can 'see' a piece of data then the GC can't recycle that piece.
Don't overthink this.
Suppose you had used:
return m.GetBuffer();
Now you are returning the internal buffer of the MemStream. m will be Disposed but simply because you returned it, the buffer will outlive its owner.
I think the answer to your question is "Not in this case".
The memory stream could of course be disposed, however before that you'll have your data in byte[] array, which will stay.
Try adding writer.Flush(); just after your writer.Write(this.Data);.
No, there is no problem. The stream will not be disposed too early.
You talk about the GC, but the idea with using statements and IDisposable is that any resource will freed immediately when the object goes out of scope. We won't have to wait for the GC. In other words this has no relation to the GC.

Do you need to call Flush() on a stream or writer if you are using the “using” statement?

I am not sure whether I need to call Flush() on the used objects if I write something like this:
using (FileStream...)
using (CryptoStream...)
using (BinaryWriter...)
{
// do something
}
Are they always automatically flushed? When does the using statement flush them and when it doesn’t (if that can happen)?
As soon as you leave the using block’s scope, the stream is closed and disposed. The Close() calls the Flush(), so you should not need to call it manually.
It varies, Stream by default does not call Flush() in the Dispose method with a few exceptions such as FileStream. The reason for this is that some stream objects do not need the call to Flush as they do not use a buffer. Some, such as MemoryStream explicitly override the method to ensure that no action is taken (making it a no-op).
This means that if you'd rather not have the extra call in there then you should check if the Stream subclass you're using implements the call in the Dispose method and whether it is necessary or not.
Regardless, it may be a good idea to call it anyway just for readability - similar to how some people call Close() at the end of their using statements:
using (FileStream fS = new FileStream(params))
using (CryptoStream cS = new CryptoStream(params))
using (BinaryWriter bW = new BinaryWriter(params))
{
doStuff();
//from here it's just readability/assurance that things are properly flushed.
bW.Flush();
bW.Close();
cS.Flush();
cS.Close();
fS.Flush();
fS.Close();
}

What is the difference between StreamWriter.Flush() and StreamWriter.Close()?

What is the difference in functionality between StreamWriter.Flush() and StreamWriter.Close()?
When my data wasn't being written correctly to a file, I added both Flush() and Close() to the end of my code. However, I realized that adding either Flush() or Close() allowed the data to be written correctly.
I wasn't able to pick up on exactly what each of these methods does when I read the MSDN docs; I only figured out that one or the other is necessary to ensure data is written correctly. Any further explanation would be much appreciated.
Where s is a string to be written, here's what my code looks like currently:
StreamWriter sw = File.CreateText("TextOutput.txt");
sw.Write(s);
sw.Flush();
sw.Close();
Based on feedback from the answers, I've rewritten my code in a using block, which implements IDisposable and will automatically take care of writing the stream to the file when the object is disposed:
using (StreamWriter sw = File.CreateText("TextOutput.txt"))
{
sw.Write(s);
}
StreamWriter.Flush() can be called any time you need to clear the buffer, and the stream will remain open.
StreamWriter.Close() is for closing the stream, at which point the buffer is also flushed.
But you shouldn't really need to call either of these. Any time I see a .Close() in code I take that as a code smell, because it usually means an unexpected exception could cause the resource to be left open. What you should do, is create your StreamWriter variable in a using block, like this:
using (var writer = new StreamWriter("somefilepath.txt"))
{
// write a bunch of stuff here
} // the streamwriter WILL be closed and flushed here, even if an exception is thrown.
StreamWriter.Flush() will flush anything in the Stream out to the file. This can be done in the middle of using the Stream and you can continue to write.
StreamWriter.Close() closes the Stream for writing. This includes Flushing the Stream one last time.
There's a better way to do things though. Since StreamWriter implements IDisposable, you can wrap the StreamWriter in a using block.
using(StreamWriter sw = new StreamWriter(stream))
{
// Work with things here
}
After the using block, Dispose will be called...which will Flush and Close the Stream for you.
I had a case where I was writing a very long string to a StreamWriter with an underlying MemoryStream. The MemoryStream was being consumed by something else before the writer and the stream were disposed.
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream , Encoding.UTF8))
{
streamWriter.Write(someRealyLongStringValue);
DoSomethingWithTheStream(memoryStream );
}
With really long strings the end of the string was being truncated. This was resolved by calling flush before the stream was used. Alternatively I could have set AutoFlush to true.
From MSDN:
Flush: Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.
Close: Closes the current StreamWriter object and the underlying stream.

How can I stop IIS 7 locking .XSLT file in C#

I have the following lines of code:
xslt.Load(XmlReader.Create(new FileStream(#"C:\website\TransList.xslt", System.IO.FileMode.Open)));
xslt.Transform(mydoc.CreateReader(),null, sw);
It works fine, if I stop the project and launch it again, I get the following error:
[System.IO.IOException] = {"The process cannot access the file 'C:\website\TransList.xslt' because it is being used by another process."}
I then have have to goto the command line and do a IISRESET to get, I can also reset the app pool, this is easiest at this time as this is just my dev box.
Now I do have the call in a try catch statement, but I cannot access the xslt object in the handler.
The xslt object doesn't seem to have a close or dispose method.
The garbage collector never gets a shot at it , it seems.
Any ideas?
You will need to close your FileStream and Reader, either explicitly using .Close() or via a using statement:
using (FileStream fs = new FileStream(#"C:\website\TransList.xslt", System.IO.FileMode.Open))
{
xslt.Load(XmlReader.Create(fs));
using (var reader = mydoc.CreateReader())
{
xslt.Transform(reader, null, sw);
}
}
There is no need to explicitly create a FileStream and an XmlReader, if you know the file location then you can simply pass that to the Load method, using this overload:
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(#"C:\website\Translist.xslt");
If you think you need to create a FileStream and an XmlReader then I agree with the suggestions already made, use the 'using' statement to properly close and dispose of those objects.
Filestream implements IDisposable and requires you to invoke Dispose to release external resources as well as implicit;y invoke close(). You should wrap your instantiation of Filestream in a using block as it ensures Dispose is invoked even if an exception is raised. To answer your question though, since you did not close the filestream, your process, presumably the w3wp.exe process still has a handle on the file stream and the only way you can release is it to reset iis or recycle the app pool. For future reference, just wrap the filestream in a using block to be safe.

Categories