C# – 操作大型XML文件

对于小型XML文件,利用XDocument和XMLDocument能够很方便开展读写(推荐XDocument),但问题是XDocument和XMLDocument是In-Memory类型的,随着文件大小的叠加,内部存储器消耗会尤其大,同时读写速度会降低。本文化总同盟结如下三种艺术操作大型XML文件:

写 – Write

此部分开头前,先提供2个成立空的 xml 文书档案的代码

string filePath = Directory.GetCurrentDirectory() + "/123456.xml";
if (!File.Exists(filePath))
{
    XmlDocument xdInit = new XmlDocument();
    StringBuilder sb = new StringBuilder();
    sb.Append("<?xml version=\"1.0\" encoding=\"gb2312\" ?><Root>");
    sb.Append("</Root>");
    string strXml = sb.ToString();
    xdInit.LoadXml(strXml);
    xdInit.Save(filePath);
}

该措施生成的 .xml 文书档案如下

<?xml version="1.0" encoding="gb2312"?>
<Root>
</Root>

或采取如下代码

if (!System.IO.File.Exists(filePath))
{
    System.IO.File.Create(filePath).Close();
    XDocument xdInit = new XDocument(
        new XElement("Root"));
    xdInit.Save(filePath);
    xdInit = null;
}

该情势生成的 .xml 文书档案如下

<?xml version="1.0" encoding="utf-8"?>
<Root />

留意,以上2种格式等同,xml 文书档案默许的编码格局是 utf-8。

在拼接 xml 字符串时,要特别注意非法字符的转义处理:

System.Security.SecurityElement.Escape(str)

向已存在的巨型XML文件中扩充新结点,无法采取In-Memory的格局。推荐如下二种写方法:

1. XStreamingElement

标题引出:怎么着巨型xml文件

应用示例

C# 1C# 2

 1 // Filepath:带写.xml文件路径;FindKey:待查找结点名称
 2 // xeList:要新增的XElement结点列表
 3 string FindKey = "Task";
 4 var items = XStreamingElementHelper(Filepath, FindKey);
 5 items = items.Concat(xeList); 
 6 var xml = new XStreamingElement
 7     ("Root",
 8         from item in items
 9         select item
10     );
11 
12 // 文件替换
13 var newFile = Filepath + "TEMP";
14 xml.Save(newFile);
15 System.IO.File.Delete(Filepath);
16 System.IO.File.Move(newFile, Filepath);
17 
18 GC.Collect();

XStreamingElement达成写文件写

参考

XStreamingElement类 –
msdn
.aspx);

How to: Perform Streaming Transform of Large XML Documents (C#) –
msdn

关于XStreamingElement vs
XElement

 Linq to
Xml:XStreamingElement

2. XML文件包涵方法

使用包括文件 .txt 和 .xml实现大型XML文件的可行扩大操作以及修改操作:

  • .xml:格式正确的标准XML文件
  • .txt:XML片段

格式正确的XML文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Root [<!ENTITY events SYSTEM "people.txt">]>
<Root>&events;</Root>

上面代码中,必须是 &,而不能够是
&

演示代码

C# 3C# 4

 1 string fileName = "sqh";
 2 string fileDir = Directory.GetCurrentDirectory() + "/";
 3 string xmlFilepath = fileDir + fileName + ".xml";
 4 string txtFilepath = fileDir + fileName + ".txt";
 5 if(!File.Exists(xmlFilepath))
 6 {
 7     // 创建.txt文件
 8     File.Create(txtFilepath).Close();
 9     
10     // 创建.xml文件
11     string type = string.Format("<!ENTITY events SYSTEM \"{0}.txt\">", fileName);
12     XDocument XDoc = new XDocument(
13         new XDocumentType("Root", null, null, type),
14         new XElement("Root", "&events;")
15         );
16     XDoc.Save(xmlFilepath);
17 }
18 else
19 {
20     StreamWriter sw = File.AppendText(txtFilepath);
21     XmlTextWriter xtw = new XmlTextWriter(sw);
22     xtw.Formatting = Formatting.Indented;  // 缩进格式
23     xtw.Indentation = 2;
24     
25     // 新增结点
26     xtw.WriteStartElement("event");
27     xtw.WriteElementString("key", "value");
28     xtw.WriteEndElement();
29     
30     xtw.WriteWhitespace(Environment.NewLine); // 换行,必须带
31     xtw.Close();
32 }

XML = .xml + .txt

地点代码创造的XML文件,& 会被转义成 & 是不当的,使用上边包车型地铁制造格局

XmlDocument xd = new XmlDocument();
string head = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
string docType = string.Format("<!DOCTYPE Root [<!ENTITY Persons SYSTEM \"{0}.txt\">]>", txtFileName);
string rootBody = "<Root>&Persons;</Root>";
StringBuilder sb = new StringBuilder();
sb.Append(head); sb.Append(docType); sb.Append(body);
string strXml = sb.ToString();
xd.LoadXml(strXml);
xd.Save(filePath);

只顾,每写三遍.txt文件,必须添加如下代码,不然会出现结点粘结的意况

xtw.WriteWhitespace(Environment.NewLine);

那里能够运用 StreamWriter,亦可使用 FileStream,代码如下

FileStream filestream = new FileStream(FileName, FileMode.Append);
XmlTextWriter xtw = new XmlTextWriter(filestream, Encoding.Default);
xtw.Formatting = Formatting.Indented;
xtw.Indentation = 2;
... ...
xtw.Close();
filestream.Close();

若使用该 .txt + .xml
方法,应使用如下情势读取 .xml 文件

XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;  // 必须的
settings.ValidationType = ValidationType.None; // 可选的
settings.IgnoreComments = true;
//settings.IgnoreWhitespace = true;  // 视while{}中代码情况
XmlReader rd = XmlReader.Create(filepath, settings);

while (rd.Read())
{
    if (rd.NodeType == XmlNodeType.Element && rd.Name == "person")
    { ... }   
}

留神,因为要采取 XmlReaderSettings 设置读取配置,由此只能选取XmlReader,而不能够采纳如下代码

XmlTextReader rd = new XmlTextReader(filepath);

参考修改大型 XML
文件的管用办法 –
MSDN

3. log4net

引用:using log4net.dll

标题引出:如何log4net to xml?

什么样采纳:Write a class Deriving from XmlLayoutBase,
override the FormatXml method and instruct your appender to
use. 

4. 文本拆分

xml/txt
写文件时,文件会愈发大,能够安装时间点或然文件大小限制,将大文件拆分成四个小文件。

// 文件大小
FileInfo fileInfo = new FileInfo(FilePath);
double fileSize = System.Math.Ceiling(fileInfo.Length / 1024.0);

该办法能够利用
log4net 实现,具体可参看:log4net –
sqh

C#,参考

关于XML格式化的题目xml日志乱码的题目

何以选取log4net写XML

读 – Read

使用XmlReader或XmlTextReader流式加载、解析XML文件。

static IEnumerable<XElement> XStreamingElementHelper(string uri, string FindKey)
{
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.IgnoreComments = true;
    settings.IgnoreWhitespace = true;

    using (XmlReader rd = XmlReader.Create(uri, settings))
    {
        rd.MoveToContent();
        while (!rd.EOF)
        {
            if(rd.NodeTyp == XElement && rd.Name == FindKey)
            {
                XElement item = XElement.ReadFrom(rd) as XElement;
                if (item != null)
                {
                    yield return item;
                }
            }
            else
            {
                rd.Read();
            }
        }
    }
}

其中,内部用XElement操作。  

相关文章