在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
对于小型XML文件,利用XDocument和XMLDocument可以很方便进行读写(推荐XDocument),但问题是XDocument和XMLDocument是In-Memory类型的,随着文件大小的增大,内存消耗会越来越大,同时读写速度会降低。本文总结如下几种方式操作大型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操作。 写 - Write此部分开始前,先提供一个创建空的 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 字符串时,要特别注意非法字符的转义处理:
向已存在的大型XML文件中追加新结点,不能采用In-Memory的方式。推荐如下几种写方法: 1. XStreamingElement 问题引出:如何巨型xml文件; 使用示例 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(); 参考: 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 version="1.0" encoding="utf-8"?> <!DOCTYPE Root [<!ENTITY events SYSTEM "people.txt">]> <Root>&events;</Root> 上面代码中,必须是 &,而不能是 & 示例代码 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文件,& 会被转义成 & 是错误的,使用下面的创建方式 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文件,必须添加如下代码,否则会出现结点粘结的情况
此处可以使用 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); 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; 参考 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论