我需要生成一个 XML 文件,并且我需要将尽可能多的数据粘贴到其中,但是有文件大小限制。因此,我需要继续插入数据,直到不再有其他内容为止。如何在不重复将其写入文件的情况下计算 XML 文件大小?
3 回答
我同意约翰桑德斯的观点。这里有一些代码基本上可以完成他所说的,但作为 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
通常,即使关闭所有打开的标记,也不能在任意位置破坏 XML 文档。
但是,如果您需要将 XML 文档拆分为多个文件,每个文件不超过特定大小,那么您应该创建自己的Stream
类的子类型。这个“ PartitionedFileStream
”类可以写入特定文件,直到大小限制,然后创建一个新文件,然后写入该文件,直到大小限制,等等。
这会给您留下多个文件,这些文件在连接时构成一个有效的 XML 文档。
在一般情况下,关闭标签不起作用。考虑一种 XML 格式,它必须包含一个元素 A,后跟一个元素 B。如果您在编写元素 A 后关闭了标签,那么您没有有效的文档 - 您需要编写元素 B。
但是,在简单站点地图文件的特定情况下,可能只关闭标签。
您可以询问XmlTextWriter
for it's BaseStream
,然后检查 it's Position
。正如其他人指出的那样,您可能需要保留一些空间来正确关闭 Xml。