1

我需要生成一个 XML 文件,并且我需要将尽可能多的数据粘贴到其中,但是有文件大小限制。因此,我需要继续插入数据,直到不再有其他内容为止。如何在不重复将其写入文件的情况下计算 XML 文件大小?

4

3 回答 3

2

我同意约翰桑德斯的观点。这里有一些代码基本上可以完成他所说的,但作为 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
于 2010-02-21T23:26:59.810 回答
1

通常,即使关闭所有打开的标记,也不能在任意位置破坏 XML 文档。

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

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


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

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

于 2010-02-21T22:39:25.447 回答
0

您可以询问XmlTextWriterfor it's BaseStream,然后检查 it's Position。正如其他人指出的那样,您可能需要保留一些空间来正确关闭 Xml。

于 2010-02-21T22:34:29.047 回答