使用.NET XmlTextWriter检查输出大小

时间:2010-02-21 22:20:52

标签: c# .net xml xmltextwriter

我需要生成一个XML文件,我需要尽可能多地将数据加入其中但是存在文件大小限制。所以我需要继续插入数据,直到某些内容不再发布。如何在不重复写入文件的情况下找出XML文件大小?

3 个答案:

答案 0 :(得分:2)

我同意John Saunders的观点。这里有一些代码基本上可以完成他正在讨论的内容,但作为一个XmlSerializer,除了作为FileStream并使用MemoryStream作为中间存储。扩展流可能更有效。

public class PartitionedXmlSerializer<TObj>
{
    private readonly int _fileSizeLimit;

    public PartitionedXmlSerializer(int fileSizeLimit)
    {
        _fileSizeLimit = fileSizeLimit;
    }

    public void Serialize(string filenameBase, TObj obj)
    {
        using (var memoryStream = new MemoryStream())
        {
            // serialize the object in the memory stream
            using (var xmlWriter = XmlWriter.Create(memoryStream))
                new XmlSerializer(typeof(TObj))
                    .Serialize(xmlWriter, obj);

            memoryStream.Seek(0, SeekOrigin.Begin);

            var extensionFormat = GetExtensionFormat(memoryStream.Length);

            var buffer = new char[_fileSizeLimit];

            var i = 0;
            // split the stream into files
            using (var streamReader = new StreamReader(memoryStream))
            {
                int readLength;
                while ((readLength = streamReader.Read(buffer, 0, _fileSizeLimit)) > 0)
                {
                    var filename 
                        = Path.ChangeExtension(filenameBase, 
                            string.Format(extensionFormat, i++));
                    using (var fileStream = new StreamWriter(filename))
                        fileStream.Write(buffer, 0, readLength);
                }
            }
        }
    }

    /// <summary>
    /// Gets the a file extension formatter based on the 
    /// <param name="fileLength">length of the file</param> 
    /// and the max file length
    /// </summary>
    private string GetExtensionFormat(long fileLength)
    {
        var numFiles = fileLength / _fileSizeLimit;
        var extensionLength = Math.Ceiling(Math.Log10(numFiles));
        var zeros = string.Empty;
        for (var j = 0; j < extensionLength; j++)
        {
            zeros += "0";
        }
        return string.Format("xml.part{{0:{0}}}", zeros);
    }
}

要使用它,您需要使用最大文件长度对其进行初始化,然后使用基本文件路径然后使用对象进行序列化。

public class MyType
{
    public int MyInt;
    public string MyString;
}

public void Test()
{
    var myObj = new MyType { MyInt = 42, 
                             MyString = "hello there this is my string" };
    new PartitionedXmlSerializer<MyType>(2)
        .Serialize("myFilename", myObj);
}

此特定示例将生成分区为

的xml文件
myFilename.xml.part001
myFilename.xml.part002
myFilename.xml.part003
...
myFilename.xml.part110

答案 1 :(得分:1)

通常,即使关闭所有打开的标记,也无法在任意位置中断XML文档。

但是,如果您需要将XML文档拆分为多个文件(每个文件不超过一定大小),那么您应该创建自己的Stream类子类型。这个“PartitionedFileStream”类可以写入特定文件,达到大小限制,然后创建一个新文件,并写入该文件,直到大小限制等。

这将为您留下多个文件,这些文件在连接时会组成一个有效的XML文档。


在一般情况下,结束标签不起作用。考虑一个必须包含一个元素A后跟一个元素B的XML格式。如果在编写元素A之后关闭了标记,那么就没有有效的文档 - 您需要有书面元素B.

但是,在简单站点地图文件的特定情况下,可以关闭标记。

答案 2 :(得分:0)

您可以向XmlTextWriter询问BaseStream,并查看Position。 正如对方指出的那样,您可能需要保留一些空间来正确关闭Xml。