在添加到MemoryStream之前,如何检查添加到MemoryStream的结果?

时间:2013-07-23 15:44:22

标签: c# memorystream

我正在使用内存流创建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文件,然后启动新文件。

2 个答案:

答案 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);