Why is FileStream not closed by XmlReader
Solution 1
Have you tried this?
using(var stream = new FileStream(archivePath, FileMode.Open))
using(var reader = XmlReader.Create(stream, readerSettings))
{
}
I couldn't find anything in the documentation that explicitly stated that the XmlReader
would call dispose on the underlying stream when it was disposed. Also, I always use it as shown above and I have never encountered a problem.
Browsing through reflector I also find no instances where it calls Dispose()
on the stream when creating a XmlTextReaderImpl
. The XmlTextReaderImpl
does not implement Dispose()
and its Close()
method looks like this:
internal void Close(bool closeInput)
{
if (this.parsingFunction != ParsingFunction.ReaderClosed)
{
while (this.InEntity)
{
this.PopParsingState();
}
this.ps.Close(closeInput);
this.curNode = NodeData.None;
this.parsingFunction = ParsingFunction.ReaderClosed;
this.reportedEncoding = null;
this.reportedBaseUri = string.Empty;
this.readState = ReadState.Closed;
this.fullAttrCleanup = false;
this.ResetAttributes();
}
}
Solution 2
You should be able to control this through XmlReaderSettings.CloseInput.
readerSettings.CloseInput = true;
using (XmlReader reader = XmlReader.Create(new FileStream(archivePath, FileMode.Open), readerSettings))
{
// do work with the reader
}
Or, more concisely if you don't care about other reader settings:
using (XmlReader reader = XmlReader.Create(new FileStream(archivePath, FileMode.Open), new XmlReaderSettings() { CloseInput = true }))
{
// do work with the reader
}
Solution 3
You would need to keep track of the FileStream
and the XmlReader
. It's potentially dangerous for the XmlReader
to close the underlying stream. In the case where the FileStream
is used by multiple readers: if one of these readers were to close the stream this would cause the other readers to fail unexpectedly.
It's a bit of a pain since some stream readers and writers will close the underlying stream, while others don't. As a best practice I always close and dispose of the streams I open manually. This also helps mitigate some 'gotchas' with certain streams.
e.g. You need to dispose a GZipStream
before calling .ToArray()
TOMMY WANG
Updated on June 30, 2022Comments
-
TOMMY WANG almost 2 years
So I am using the
FileStream
insideXmlReader
using (XmlReader reader = XmlReader.Create(new FileStream(archivePath, FileMode.Open), readerSettings)) { reader.close() }
However, the file feed into the
XmlReader
is still in the lock state after theusing
scope, weird, I thought theXmlReader
is going to close theFileStream
for me, is it not?Thanks for help.
-
TOMMY WANG about 12 yearsto be honest, no. I thought XmlReader is like StreamReader, will close the inner stream once done. use two using statement is just a bit clumsy.
-
Grant H. about 12 yearsAnecdotal, but most of the examples I see use the two
using
's. -
Ed S. about 12 years@TOMMYWANG: Well you may think so, but I cannot find anywhere in the code (using reflector) where
XmlTextReaderImpl
(which is whatXmlReader.Create()
actually returns) disposes of the stream. If it did close the stream you would run into problems when using one stream for multiple readers (what if I want to keep the stream alive? Why should the reader decide that I can't?), so it takes the safe approach of doing nothing. I don't agree that it is "clumsy', but 'clumsy' is better than 'broken'. -
Ed S. about 12 years@TOMMYWANG: NP, glad to help :)
-
satnhak about 10 yearsGood answer, this stops FxCop from complaining about multiple disposals if you set CloseInput = false, which was annoying me.
-
Josh M. over 8 yearsI'd rather an underlying stream not be closed by a reader because you may still want to use the stream afterwards, but can't since it would have been closed! So this is the best behavior IMO.
-
Kent over 6 yearsIsn't the reader.close() statement here redundant since exiting the using statement will call Dispose() and that calls Close()?