在 XmlWriter 周围使用语句会导致过早关闭流
Using statement around XmlWriter causes premature closing of stream
我正在尝试将一小段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);
但是用 XmlWriter
替换 StreamWriter
并尝试写入实际的 XML 结果是 ObjectDisposedException
.
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()
但是如果我删除 XmlWriter
周围的 using
块...它会起作用。
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);
我无法理解为什么会发生这种情况以及为什么我不能在 TextWriter
周围使用 using
块。用 StreamWriter
完成的相同步骤工作得很好,那么 XmlWriter
有什么区别?我假设在使用块结束之前不会关闭流。我的思路哪里出了问题?
默认情况下StreamReader
处理底层流。如果在释放 StreamReader
后需要它(并且 XmlWriter
使用它来执行 Flush
),您可以将 leaveOpen
ctor 参数设置为 true
:
using (var streamReader = new StreamReader(memoryStream, leaveOpen: true))
查看堆栈跟踪:异常发生在 XmlWriter
被处置时,在其块的末尾。它被处理,它刷新,它尝试写入底层流并砰! - 某些东西已经处理了底层流。
StreamReader
的块在 XmlWriter
的块之前结束,并且此处置也(默认情况下)处置底层流。这是唯一可以做到的事情。
它在其他情况下工作的原因是 StreamWriter
不能在处理时刷新(或者更有可能 - 它 不需要 刷新因为它的缓冲区要么是空的,要么是 non-existing)。这意味着 StreamReader
在它之前已经介入并不重要。
在最后一种情况下它起作用是因为 XmlWriter
没有被处理,并且根本没有试图刷新(但是,它显然不需要,因为你已经手动刷新,输出正确 - 我想知道为什么它的 dispose 方法坚持要刷新?但它正在做)
这里一般的解决办法是更有选择性地使用using
。你可以完全错过 StreamReader
,也可以将 'leaveOpen' 参数传递给它。
我通常的方法是只担心处理流,因为它始终是链接到需要处理的非托管资源的流。读者和作家的处置实际上只是一种简洁地处置流的好方法。
我正在尝试将一小段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);
但是用 XmlWriter
替换 StreamWriter
并尝试写入实际的 XML 结果是 ObjectDisposedException
.
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()
但是如果我删除 XmlWriter
周围的 using
块...它会起作用。
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);
我无法理解为什么会发生这种情况以及为什么我不能在 TextWriter
周围使用 using
块。用 StreamWriter
完成的相同步骤工作得很好,那么 XmlWriter
有什么区别?我假设在使用块结束之前不会关闭流。我的思路哪里出了问题?
默认情况下StreamReader
处理底层流。如果在释放 StreamReader
后需要它(并且 XmlWriter
使用它来执行 Flush
),您可以将 leaveOpen
ctor 参数设置为 true
:
using (var streamReader = new StreamReader(memoryStream, leaveOpen: true))
查看堆栈跟踪:异常发生在 XmlWriter
被处置时,在其块的末尾。它被处理,它刷新,它尝试写入底层流并砰! - 某些东西已经处理了底层流。
StreamReader
的块在 XmlWriter
的块之前结束,并且此处置也(默认情况下)处置底层流。这是唯一可以做到的事情。
它在其他情况下工作的原因是 StreamWriter
不能在处理时刷新(或者更有可能 - 它 不需要 刷新因为它的缓冲区要么是空的,要么是 non-existing)。这意味着 StreamReader
在它之前已经介入并不重要。
在最后一种情况下它起作用是因为 XmlWriter
没有被处理,并且根本没有试图刷新(但是,它显然不需要,因为你已经手动刷新,输出正确 - 我想知道为什么它的 dispose 方法坚持要刷新?但它正在做)
这里一般的解决办法是更有选择性地使用using
。你可以完全错过 StreamReader
,也可以将 'leaveOpen' 参数传递给它。
我通常的方法是只担心处理流,因为它始终是链接到需要处理的非托管资源的流。读者和作家的处置实际上只是一种简洁地处置流的好方法。