我正在使用内存流创建XML文件,方法如下 -
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
MemoryStream ms = new MemoryStream();
using (XmlWriter writer = XmlWriter.Create(ms, settings))
{
// CREATE XML WITH STATEMENTS LIKE THIS
writer.WriteStartElement("url", myUrl);
writer.WriteEndElement();
}
在将元素实际添加到MemoryStream
之前,有没有办法检查结果MemoryStream
的长度是多少?
像 -
var sizeTotal = ms + (writer.WriteStartElement("url", myUrl);
这样做的目的是让我检查sizeTotal
,确保在我将其写入MemoryStream
之前不要太大。
我生成的XML文件的大小限制为10MB。我可以写入“临时”流1,检查长度,如果sizeTotal
小于10MB,则将元素写入“真实”流。否则,如果sizeTotal
超过10MB,我想不将元素添加到流中,生成XML文件,然后启动新文件。
答案 0 :(得分:1)
在我实际编写元素之前,我无法确定元素的长度。但是可以确定事情的持续时间,然后在需要时进行备份。关键是在开始写入之前获取MemoryStream
的当前位置,并在写入之后从位置中减去该位置。例如:
using (XmlWriter writer = XmlWriter.Create(ms, settings))
{
long startPos = ms.Position;
// write an element
writer.WriteStartElement("url", myUrl);
writer.WriteEndElement();
writer.Flush(); // make sure data is flushed to the stream
long endPos = ms.Position;
}
因此,如果endPos
超出了您的大小限制,您可以将内存流从0复制到startPos
,然后保存。然后,您可以将流定位为0并重试您的写入。类似的东西:
using (XmlWriter writer = XmlWriter.Create(ms, settings))
{
// write an element
while (true)
{
long startPos = ms.Position;
writer.WriteStartElement("url", myUrl);
writer.WriteEndElement();
writer.Flush(); // make sure data is flushed to the stream
if (ms.Position < maxSize)
break;
// here, copy memory buffer from 0 to startPos and save to disk
// then, reset position
ms.Position = 0;
}
// write another element
while (true)
{
// same thing, different element
}
// make sure to write the final buffer!
}
这是一般的想法。当然,如果单个元素超过阈值,您需要确保不进入无限循环。
请注意,我没有解决XML片段的问题,这种技术无疑会产生这种问题。如果您希望单个文件是有效的XML,则必须跟踪打开的元素,因此在编写部分文件时,所有这些元素都将被关闭。初始化下一位的内存流时,还需要打开这些元素。您可以使用ms.Position = 0;
代替{{1}},也可以在编写下一个片段时执行此操作。
如果不了解更大的问题(即你对这些部分文件做了什么),我无法就如何处理它提出具体的建议。
答案 1 :(得分:0)
你的意思是这样的吗?
var myUrl = "http://www.stackoverflow.com";
var encoding = Encoding.UTF8;
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.Encoding = encoding;
var SOME_MAX_SIZE_IN_BYTES = 1024;
MemoryStream ms = new MemoryStream();
for(var i=0; i<10; i++)
{
using (XmlWriter writer = XmlWriter.Create(ms, settings))
{
// CREATE XML WITH STATEMENTS LIKE THIS
writer.WriteStartElement("url", myUrl);
writer.WriteEndElement();
// in order to get a semi-accurate byte count,
// you need to force the flush to the underlying stream
writer.Flush();
var lengthInBytes = ms.Length;
if(lengthInBytes > SOME_MAX_SIZE_IN_BYTES)
{
Console.WriteLine("TOO BIG!");
break;
}
}
}
var xml = encoding.GetString(ms.ToArray());
Console.WriteLine(xml);