`
rhj485hm
  • 浏览: 13890 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

C#实现Xml日志记录文件的最优方案

阅读更多

C#实现Xml日志记录文件的最优方案
2012年01月05日
  本文和大家讲解分享一下使用C#来实现Xml日志记录文件的方案。
  Xml作为数据存储的一种方式,当数据非常大的时候,我们将碰到很多Xml处理的问题。通常,我们对Xml文件进行编辑的最直接的方式是将xml文件加载到XmlDocument,在内存中来对XmlDocument进行修改,然后再保存到磁盘中。这样的话我们将不得不将整个XML document 加载到内存中,这明显是不明智的(对于大数据XML文件来说,内存将消耗很大,哥表示鸭梨很大)。下面我们将要讲的是如何高效的增加内容(对象实体内容)到xml日志文件中。
  
  (一)设计概要
  总体来说,我们将(通过代码)创建两种不同的文件,第一种为Xml文件,第二种为xml片段(txt文件),如下图所示:
  我们通过如下的定义来使2个不同的文件相关联。
  
  (二)xml文件的生成
  先来看下如何创建相关的xml文件,代码如下:
  Code [http://www.xueit.com]        private static void InitXmlFile(string xmlLogFilePath, string xmlLogContentFileName, string entityRef)
  {
  string docType = string.Format("\n\n ]>\n", entityRef, xmlLogContentFileName);
  XmlWriterSettings wrapperSettings = new XmlWriterSettings()
  {
  Indent = true
  };
  using (XmlWriter writer = XmlWriter.Create(xmlLogFilePath, wrapperSettings))
  {
  writer.WriteStartDocument();
  writer.WriteRaw(docType);
  writer.WriteStartElement(ConfigResource.XmlLogFile );
  writer.WriteStartElement(ConfigResource.XmlLogCont ent);
  writer.WriteEntityRef(entityRef);
  writer.WriteEndElement();
  writer.WriteEndElement();
  writer.Close();
  }
  }对xml文件内容的写入主要通过XmlWriter来进行操作的。这个方法比较简单,不再讲解,看下我们通过这个方法生成的文件内容:
  Code [http://www.xueit.com]
  
  ]>
  
  &Locations;
  Locations 为实体引用名称,与之相对应的为&Locations;   。
  XmlLogContentFile-20110220000120.txt为Xml片段的文件名称,路径是相对于XmlLogFile-20110220000120.xml的。
  &Locations;相当于占位符的作用,将用XmlLogContentFile-20110220000120.txt文件的内容来替换XmlLogFile-20110220000120.xml的&Locations;
  分享C#实现Xml日志记录文件的最优方案
  时间:2011-2-21 9:21:28 来源:www.cnblogs.com 作者:JasenKin  
  -
  -
  输出内容如下:
  
  (四)采用lock来避免异常的发生,其次特别要注意对资源的及时释放。
  Code [http://www.xueit.com]        private static readonly object lockObject = new object();
  public static void Write(object logObject)
  {
  if (logObject == null)
  {
  return;
  }
  lock (lockObject)
  {
  Writing(logObject);
  }
  }
  private static void Writing(object logObject)
  {
  string entityRef = ConfigResource.EntityRef;
  string baseDirectory = InitDirectory();
  string baseName = DateTime.Now.ToString("yyyyMMddHHmmss");
  string xmlLogFilePath =Path.Combine(baseDirectory ,string.Format(ConfigResource.XmlLogFileName,baseN ame));
  XmlLogHelper.XmlFilePath = xmlLogFilePath;
  string xmlLogContentFileName = string.Format(ConfigResource.XmlLogContentFileName ,baseName);
  string xmlLogContentFilePath = Path.Combine(baseDirectory, xmlLogContentFileName);
  if (!File.Exists(xmlLogFilePath))
  {
  InitXmlFile(xmlLogFilePath, xmlLogContentFileName, entityRef);
  }
  InitEntityRefFile(xmlLogContentFilePath, logObject, entityRef);
  }采用lock来避免同时对文件进行操作,避免异常的发生,保证每次操作都是仅有一个在进行。 
  lock (lockObject)
  {
  Writing(logObject);
  }
  采用using来及时释放掉资源。
  using (FileStream fileStream = new FileStream(xmlLogContentFilePath, FileMode.Append,
  FileAccess.Write, FileShare.Read))
  {
  }
  (五)单元测试
  单元测试的主要代码如下,主要是对Write()方法进行测试,如下:
  Code [http://www.xueit.com]        [TestMethod()]
  public void WriteTest()
  {
  DeleteFiles();//删除目录下所有文件,避免产生不必要的影响。
  List errors = InitErrorData(9);
  AssertXmlContent(errors);
  }
  private static void AssertXmlContent(List errors)
  {
  foreach (Error error in errors)
  {
  XmlLogHelper.Write(error);
  XmlDocument doc = GetXmlDocument();
  XmlNode node = doc.SelectSingleNode("//Error[@Id='"   error.GetHashCode().ToString()   "']");
  Assert.IsTrue(node.Name == typeof(Error).Name);
  string path = string.Format("//Error[@Id='{0}']//", error.GetHashCode().ToString());
  XmlNode levelNode = doc.SelectSingleNode(path   "Level");
  XmlNode nameNode = doc.SelectSingleNode(path   "Name");
  XmlNode descriptionNode = doc.SelectSingleNode(path   "Description");
  XmlNode timeNode = doc.SelectSingleNode(path   "Time");
  XmlNode pointNode = doc.SelectSingleNode(path   "Point");
  Assert.IsTrue(nameNode.Name == "Name");
  Assert.IsTrue(levelNode.Name == "Level");
  Assert.IsTrue(descriptionNode.Name == "Description");
  Assert.IsTrue(timeNode.Name == "Time");
  Assert.IsNotNull(levelNode);
  Assert.IsNotNull(nameNode);
  Assert.IsNotNull(descriptionNode);
  Assert.IsNotNull(timeNode);
  Assert.IsNull(pointNode);
  Assert.IsTrue(nameNode.InnerText == (error.Name ?? string.Empty));
  Assert.IsTrue(levelNode.InnerText == error.Level.ToString());
  Assert.IsTrue(timeNode.InnerText == DateTime.MinValue.ToString());
  Assert.IsTrue(descriptionNode.InnerText == (error.Description ?? string.Empty));
  }
  }上面仅仅是针对一个自定义的Error类进行了验证................
  (六)其他应用
  当我们的Xml日志文件可以记录的时候,我们可能想通过界面来看下效果,比如如下所示意的图中,点击【生成XML日志文件】,再点击【获取XML日志文件】的时候,我们能够看到生成的XML日志文件。
  
  其中生成的文件名称显示如下:
  
  多次点击【生成XML日志文件】,再点击【获取XML日志文件】的时候,我们能够看到生成的XML日志文件数量也递增(因为我将文件的名称设置为string baseName = DateTime.Now.ToString("yyyyMMddHHmmss");,按照秒数来计算的)。点击任何一个文件,将显示该文件的相关全部xml内容(包括xml文件和xml片段)。
  
  点击【删除XML日志文件】将删除所有的xml文件,如下:
  
  (七)总结
  对于流的操作来说,应尽快释放掉系统资源,促使GC的Finalize()方法的执行,同时可以避免异常的发生。对于Xml日志来说,当数据量越来越大的时候,我们可以将内容分为两部分,一部分为标准的哦xml文件,另一部分为xml片段文件。这样,我们能够在xml片段文件中方便地在文件末尾处增加相关的内容,这种效率是非常快的,而通常我们通过XMLDocument来加载数据非常消耗内存,效率较低(数据量越大越明显)。同时在读取xml文件的时候也会通过实体引用将相关的xml片段引用进来,从而使二个文件成为一个整体。再次,在将对象转换成xml的时候,通过反射来获取相关的数据,并将数据写入xml格式中,这个地方还有提高。希望各位在看完此文后也能熟练的运用XML日志文件来对日志进行记录。
  
  
  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics