问题描述
我试图将一小段XML写入内存流,然后从内存流中读取写入的内容并将其保存到变量中。
我有以下逻辑可用于编写和读取简单文本值:
string text = null;
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
{
streamWriter.Write("Foo!");
streamWriter.Flush();
memoryStream.Position = 0;
using (var streamReader = new StreamReader(memoryStream))
{
text = streamReader.ReadToEnd();
}
}
}
await context.Response.WriteAsync(text,Encoding.UTF8);
但是将StreamWriter
替换为XmlWriter
,然后尝试在ObjectdisposedException
中写入实际的XML结果。
string text = null;
using (var memoryStream = new MemoryStream())
{
using (var xmlWriter = XmlWriter.Create(memoryStream))
{
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Foo");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
memoryStream.Position = 0;
using (var streamReader = new StreamReader(memoryStream))
{
text = streamReader.ReadToEnd();
}
}
}
System.ObjectdisposedException: Cannot access a closed Stream.
at System.IO.MemoryStream.Write(Byte[] buffer,Int32 offset,Int32 count)
at System.Xml.XmlUtf8RawTextWriter.FlushBuffer()
at System.Xml.XmlUtf8RawTextWriter.Flush()
at System.Xml.XmlWellFormedWriter.Close()
at System.Xml.XmlWriter.dispose(Boolean disposing)
at System.Xml.XmlWriter.dispose()
但是,如果我删除using
周围的XmlWriter
块...,它将起作用。
string text = null;
using (var memoryStream = new MemoryStream())
{
var xmlWriter = XmlWriter.Create(memoryStream));
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Foo");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
memoryStream.Position = 0;
using (var streamReader = new StreamReader(memoryStream))
{
text = streamReader.ReadToEnd();
}
}
await context.Response.WriteAsync(text,Encoding.UTF8);
我无法理解为什么会发生这种情况,为什么我不能在using
周围使用TextWriter
块。用StreamWriter
完成的相同步骤就可以了,所以XmlWriter
有什么区别?我假设直到使用块的结尾都不会关闭流。我的思维方式的缺陷在哪里?
解决方法
看一下堆栈跟踪:XmlWriter
被放置在其块的末尾时发生了异常。它被处置,刷新,它尝试写入基础流并爆炸! -某些东西已经处置了基础流。
StreamReader
的块恰好在XmlWriter
的块之前结束,并且这种处置(默认情况下)也处置基础流。这是唯一可以做到的事情。
在其他情况下它起作用的原因是StreamWriter
不得在处置时刷新(或者更有可能-不需要 刷新,因为其缓冲区为空或不存在)。这意味着StreamReader
之前没有关系。
在最后一种情况下它有效,因为没有XmlWriter
被处置,也根本没有尝试冲洗(但是,显然,它并不需要,因为您已经手动冲洗了) ,并且输出是正确的-我想知道为什么它的dispose方法坚持要刷新吗?但是它在做)
这里的一般解决方案是更有选择地使用using
。您可以完全忽略StreamReader
,也可以将'leaveOpen'参数传递给它。
我通常的方法是只担心处理流,因为流始终是链接到需要处理的非托管资源的流。处置读者和作家实际上只是简洁地处置流的一种好方法。
,默认情况下,lib
处置基础流。如果在处置StreamReader
之后需要它(并且StreamReader
在处置过程中使用它来执行XmlWriter
),则可以将leaveOpen
ctor参数设置为Flush
:
true