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