1

我正在以下列方式使用内存流创建 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。我可以先写入“临时”流,检查长度,如果sizeTotal小于 10MB,将元素写入“真实”流。否则,如果sizeTotal超过 10MB,我不想元素添加到流中,生成 XML 文件,然后开始一个新文件。

4

2 回答 2

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;,或者您可以在写出下一个片段时这样做。

在不了解更大问题的更多信息(即您对这些部分文件所做的事情)的情况下,我无法就如何处理它提出具体建议。

于 2013-07-23T17:03:48.670 回答
0

You mean something like this?

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);
于 2013-07-23T17:00:48.453 回答