内存流为空。

4

我需要从不同的来源(函数)生成一个巨大的XML文件。我决定使用XmlTextWriter,因为它比XmlDocument使用更少的内存。

首先,使用底层的MemoryStream初始化一个XmlWriter

MemoryStream ms = new MemoryStream();
XmlTextWriter xmlWriter = new XmlTextWriter(ms, new UTF8Encoding(false, false));
xmlWriter.Formatting = Formatting.Indented;

然后我将 XmlWriter(注意,xml writer 一直保持打开状态直到最后)传递给一个函数生成 XML 文件的开头:

xmlWriter.WriteStartDocument();

xmlWriter.WriteStartElement();

// xmlWriter.WriteEndElement(); // Do not write the end of root element in first function, to add more xml elements in following functions

xmlWriter.WriteEndDocument();
xmlWriter.Flush();

但我发现底层的内存流是空的(通过将字节数组转换为字符串并输出字符串)。有什么想法吗?
另外,我有一个关于如何从不同的来源(函数)生成大型XML文件的一般问题。我现在所做的是保持XmlWriter打开(我假设底层的内存流也应该打开),然后写入每个函数。在第一个函数中,我不写根元素的结尾。在最后一个函数之后,我手动添加根元素的结尾:
string endRoot = "</Root>";
byte[] byteEndRoot = Encoding.ASCII.GetBytes(endRoot);
ms.Write(byteEndRoot, 0, byteEndRoot.Length); 

不确定这是否有效。

非常感谢!


1
你应该将这个问题分成两部分,然后再链接起来,如果它们彼此相关的话。 - Adriano Carneiro
2
请注意,MemoryStream 完全削弱了 "我决定使用 XmlTextWriter,因为它使用更少的内存"。 - H H
2
对于小于10 MB的任何内容,只需使用XmlDocument或XDocument。为了节省内存,可以写入FileStream。 - H H
@Henk,你能否详细说明一下XmlTextWriter和XmlDocument的优先选择?我之前使用过XmlDocument。但我的研究表明,在内存使用方面,XmlTextWriter更受欢迎。请参见http://support.softartisans.com/kbview_673.aspx和http://msdn.microsoft.com/en-us/library/ff647804.aspx。我的老板说我们不需要操作xml文档,并希望我再次使用XmlTextWriter编写... - Summer
只有在写入文件时,编写器才会节省内存。如果您写入 MS,则将使用与文档大致相同的内存,但没有好处。 - H H
3个回答

8

从技术上讲,您应该每次只问一个问题,所以我只会回答第一个问题,因为这只是我此刻对SO的快速访问。

我认为在尝试从流中读取之前,您需要调用Flush

编辑 只是通过下面的评论来证明我接受的答案的第二个猜测。

除了调用Flush之外,如果使用Read方法及其兄弟从流中读取,则必须首先将流中的位置重置回开头。否则不会读取任何字节。

ms.Position = 0; /*reset Position to start*/
StreamReader reader = new StreamReader(ms); 
string text = reader.ReadToEnd(); 
Console.WriteLine(text); 

我添加了xmlWriter.Flush(); 但仍然得到空的内存流。当我将xmlWriter传递给一个函数,例如:public void Function(XmlTextWriter xmlWriter),xmlWriter.WriteStartElement等操作会写入底层的内存流吗? - Summer
请发布测试内存流的代码 - 可能流是好的,而您的测试是错误的。 - Ray
@Summer - Long shot - 你是通过从流中执行标准读取循环来获取字节吗?如果是这样,那么当前位置将是流的末尾,并且您将无法从中读取任何内容。确保如果您还没有使用ToArray(),请务必使用它。 - Andras Zoltan
你说得完全正确!在测试ms之前我忘记设置ms.Position=0了。所以正确的测试应该是: ms.Position = 0; StreamReader reader = new StreamReader(ms); string text = reader.ReadToEnd(); Console.WriteLine(text); - Summer

1
也许你需要在检查内存流之前在 XML 流上调用 Flush()。

1
请确保在检查内存流之前,对XmlTextWriter调用Flush方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接