zoukankan      html  css  js  c++  java
  • 日志记录类(明确FileStreamDictionary等用法)

         一个好的程序对于日志的处理是必不可少的。好的日志记录可以帮助我们减少更好的查找错误和系统的维护。今天整理一下自己工作中平时用来记录日志的类,同时也补补基础知识。

         功能: 根据程序App.config中配置的路径,创建日志文件并将程序的日志写到相应的文件中。

         首先来看一下我之前自己写的一个用于写日志的类,源代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Configuration;
    
    namespace LogHelp
    {
        public class LogHelp
        {
            private string _filename;
            private static Dictionary<long, long> lockDic = new Dictionary<long, long>();
    
            //获取或设置文件名称
            public string FileName
            {
                get { return _filename; }
                set { _filename = value; }
            }
    
            //构造函数;根据传入的文件名,将日志写到相应的路径下的文件中。
            public LogHelp(string filename)
            {
                string folder = ConfigurationManager.AppSettings["LogPath"]+"\"+System.DateTime.Now.Date.ToString("yyyyMMdd");
                if (!System.IO.Directory.Exists(folder))
                    System.IO.Directory.CreateDirectory(folder);
                if (!filename.ToLower().EndsWith(".txt"))
                {
                    filename = filename.Split('.')[0];
                    filename += ".txt";
                }
    
                _filename = folder + "\" + filename;
            }
    
            //创建文件
            public void Create(string fileName)
            {
                if (!System.IO.File.Exists(fileName))
                {
                    using (System.IO.FileStream fs= System.IO.File.Create(fileName))
                    {
                        fs.Close();
                    }
                }
            }
    
            //写入文本
            private void Write(string content, string newLine)
            {
                if (string.IsNullOrEmpty(_filename))
                {
                    throw new Exception("FileName不能为空!");
                }
                using(System.IO.FileStream fs=new System.IO.FileStream(_filename,System.IO.FileMode.OpenOrCreate,System.IO.FileAccess.ReadWrite,System.IO.FileShare.ReadWrite,8,System.IO.FileOptions.Asynchronous))
                {
                    //FileStream只能处理字节,须通过编码将字符数据转换成字节。
                    //新建字节型数组dataArrary对象,dataArrary对象得到了content+newLine的Encoding的值
                    Byte[] dataArrary = System.Text.Encoding .Default.GetBytes(content+newLine);
                    bool flag = true;
                    long slen = dataArrary.Length;
                    long len = 0;
                    while (flag)
                    {
                        try
                        {
                            if (len >= fs.Length)
                            {
                                fs.Lock(len, slen);
                                lockDic[len] = slen;
                                flag = false;
                            }
                            else
                            {
                                len = fs.Length;
                            }
                        }
                        catch (Exception ex)
                        {
                            while (!lockDic.ContainsKey(len))
                            {
                                len += lockDic[len];
                            }
                        }
                    }
                    fs.Seek(len, System.IO.SeekOrigin.Begin); //seek设置文件的读取和写入位置
                    fs.Write(dataArrary, 0, dataArrary.Length);
                    fs.Close();
                }
            }
    
            //写入文件内容
            public void WriteLine(string content)
            {
                this.Write(content, System.Environment.NewLine);
            }
    
            //写入文件
            public void Write(string content)
            {
                this.Write(content, "");
            }
    
        }
    }
    View Code

       这个类基本就可以实现日志的记录啦,当然都是很基础的功能哈。自己在住程序中创建实体类,直接调用即可啦。

       比如我在App.config文件中配置了路径: "D:studylog", 在主程序中调用如下:

    public class Program
    {
         private static LogHelp log = new LogHelp("LogTest");
         static void Main(string[] args)
         {
             log.WriteLine("Hello World");
         }
    }
    View Code

       直接运行程序,你就可以在D:studylogyyyymmddlogtest.txt 文件中看到写入的”Hello World"啦。就这么简单,没什么可说的啦。

       好啦,接下来,我们来看一下日志类中用到的Dictionary 和FileStream 用法的一些总结,加深了解,多了解没坏处啦。

    Dictionary的用法总结:    

       需要引入命名空间: System.Collections.Generic (程序集:mscorlib)

       Dictionary<string,string>是一个泛型,他本身有集合的功能有时可以把它看成数组;

       他的结构是这样的: Dictionary<[key],[value]>,

       他的特点是存入对象是需要与[key]值一一对应的存入该泛型;

       1. 用法一、常规用

           增加键值对之前需要判断是否存在该键,如果已经存在该键而且不判断,将抛出异常。所以这样每次都要进行判断,很麻烦,在备注使用了一个扩展方法:

        构建一个Dictionary: Dictionary<string, string> plist = new Dictionary<string,string>;

        读取Dictionary中的Key和Value,判断是否包含某个Key:  plist.ContainsKey("");

        遍历Key: foreach(var key in plist.keys);

        遍历Value: foreach(string value in plist.values);

        遍历Key和Value: foreach(var dic in plist) { dic.key,dic.value};

       2. 用法二、Dictionary的value为一个数组,代码示例如下:

    public static void Sample()
    {
       Dictionary<string,string[]> dic = new Dictionary<string,string[]>();
       string[] zhejiang = {"aa","bb","cc"};  
       string[] shanghai = {“pudong","waitan"};
       dic.Add("ZJ", zhejiang);
       dic.Add("SH",shanghai);
    }

       3. 用法三、Dictionary的Value为一个类;

    public static void Sample3()
    {
       Dictionary<string, string> stuList = new Dictionary<string,string>();
       Student stu=null;
       for(int i=0; i<3;i++)
       {
          stu = new Student();
          stu.Num = i.ToString();
          stu.Name = "StuName"+i.ToString();
          stuList.Add(i.ToString(),stu);
       }
    }

    备注: Dictionary的扩展方法使用:

     
    public static void DicSample4()
    {
           //1)普通调用
            Dictionary<int, String> dict = new Dictionary<int, String>();
            DictionaryExtensionMethodClass.TryAdd(dict, 1, "ZhangSan");
            DictionaryExtensionMethodClass.TryAdd(dict, 2, "WangWu");
            DictionaryExtensionMethodClass.AddOrPeplace(dict, 3, "WangWu");
            DictionaryExtensionMethodClass.AddOrPeplace(dict, 3, "ZhangWu");
            DictionaryExtensionMethodClass.TryAdd(dict, 2, "LiSi");
    
            //2)TryAdd 和 AddOrReplace 这两个方法具有较强自我描述能力,用起来很省心,而且也简单:
            dict.AddOrPeplace(20, "Orange");
            dict.TryAdd(21, "Banana");
            dict.TryAdd(22, "apple");
    
            //3)像Linq或jQuery一样连起来写   
            dict.TryAdd(10, "Bob")
                  .TryAdd(11, "Tom")
                  .AddOrPeplace(12, "Jom");
            //4) 获取值
            String F = "Ba";
            dict.TryGetValue(31, out F);
            Console.WriteLine("F : {0}",F);
    
            foreach (var dic in dict)
            {
                Console.WriteLine("Output : Key : {0}, Value : {1}", dic.Key, dic.Value);
            }
            //5)下面是使用GetValue获取值
            var v1 = dict.GetValue(111,null);
            var v2 = dict.GetValue(10,"abc");
    
            //6)批量添加
            var dict1 = new Dictionary<int,int>();
            dict1.AddOrPeplace(3, 3);
            dict1.AddOrPeplace(5, 5);
    
            var dict2 = new Dictionary<int, int>();
            dict2.AddOrPeplace(1, 1);
            dict2.AddOrPeplace(4, 4);
            dict2.AddRange(dict1, false);
      }
      扩展方法所在的类
        public static class DictionaryExtensionMethodClass 
        {
            /// <summary>
            /// 尝试将键和值添加到字典中:如果不存在,才添加;存在,不添加也不抛导常
            /// </summary>
            public static Dictionary<TKey, TValue> TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue value)
            {
                if (dict.ContainsKey(key) == false)
                    dict.Add(key, value);
                return dict;
            }
    
            /// <summary>
            /// 将键和值添加或替换到字典中:如果不存在,则添加;存在,则替换
            /// </summary>
            public static Dictionary<TKey, TValue> AddOrPeplace<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue value)
            {
                dict[key] = value;
                return dict;
            }
    
            /// <summary>
            /// 获取与指定的键相关联的值,如果没有则返回输入的默认值
            /// </summary>
            public static TValue GetValue<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultValue)
            {
                return dict.ContainsKey(key)?dict[key] : defaultValue;
            }
    
            /// <summary>
            /// 向字典中批量添加键值对
            /// </summary>
            /// <param name="replaceExisted">如果已存在,是否替换</param>
            public static Dictionary<TKey, TValue> AddRange<TKey, TValue>(this Dictionary<TKey, TValue> dict, IEnumerable<KeyValuePair<TKey, TValue>> values, bool replaceExisted)
            {
                foreach (var item in values)
                {
                    if (dict.ContainsKey(item.Key) == false || replaceExisted)
                        dict[item.Key] = item.Value;
                }
                return dict;
            }
    
    
        }
    View Code

       其他常见的属性和方法的说明:

       Comparer:  获取用于确定字段中键是否相等的IEqualityComparer;

       Count:        获取包含在Dictionary中键值对的数目;

       Item:           获取或设置与指定的键相关联的值;

       Keys:          获取包含Dictionary中键的集合;

       Values:       获取包含Dictionary中的值的集合;

       Add:            将指定的键和值添加到字典中;

       Clear:          从Dictionary中移除所有的键和值;

       ContainsKey: 确定Dictionary是否包含指定的键;

       ContainsValue: 确定Dictionary是否包含特定值;

       GetEnumerator: 返回循环访问Dictionary的枚举值;

       GetType:      获取当前实例的Type(从Object继承);

       Remove:      从Dictionary中移除所指定的键的值;

       ToString:      返回表示当前Object的String.(从Object继承);

       TryGetValue:  获取与指定的键相关联的值。

    FileStream用法总结:

       引用命名空间: using System.IO

       FileStream类只能处理原始字节(raw byte)。FileStream类可以用于任何数据文件,而不仅仅是文本文件。FileStream对象可以用于读取诸如图像和声音的文件,FileStream读取出来的是字节数组,然后通过编码转换将字节数组转换成字符串。

       1. 读取文件:

           第一步: 声明一个FileStream类的对象:

           FileStream fsRead = new FileStream(string path, FileMode mode, FileAccess access);

           参数:

           path: 要操作文件的路径,路径可以是绝对路径或者相对路径;

           mode: 操作文件的方式,打开或者创建;

           access: 操作文件中的数据,读取或者写入。

           第二步: 调用fsRead对象的方法Read;

          下面方法是从文件中读取数据,再把数据写入一个字节数组;

           FileStream.Read(byte[] array, int offset, int count);

           参数:

           array: 用了存储fsRead对象读取到数据的字节数组;

           offset: 开始读取数据的位置,通常是0.

           count: 最多读取的字节数。

       2. 写入文件:

           第一步: 声明一个FileStream类的对象:

           FileStream fsWrite = new FileStream(string path, FileMode mode, FileAccess access);

           第二步: 调用fsWrite对象的方法Write;

           FileStream.Write(byte[] array, int offset, int count): 将字节数组数据写入到指定的文本。           

    FileStream常用的属性和方法:

    属性:

    CanRead 判断当前流是否支持读取,返回bool值,True表示可以读取

    CanWrite 判断当前流是否支持写入,返回bool值,True表示可以写入

    方法:

    Read() 从流中读取数据,返回字节数组

    Write() 将字节块(字节数组)写入该流

    Seek() 设置文件读取或写入的起始位置

    Flush() 清除该流缓冲区,使得所有缓冲的数据都被写入到文件中

    Close() 关闭当前流并释放与之相关联的所有系统资源

    文件的访问方式:(FileAccess)

    包括三个枚举:

    FileAccess.Read(对文件读访问)

    FileAccess.Write(对文件进行写操作)

    FileAccess.ReadWrite(对文件读或写操作)

    文件打开模式:(FileMode)包括6个枚举

    FileMode.Append 打开现有文件准备向文件追加数据,只能同FileAccess.Write一起使用

    FileMode.Create 指示操作系统应创建新文件,如果文件已经存在,它将被覆盖

    FileMode.CreateNew 指示操作系统应创建新文件,如果文件已经存在,将引发异常

    FileMode.Open 指示操作系统应打开现有文件,打开的能力取决于FileAccess所指定的值

    FileMode.OpenOrCreate 指示操作系统应打开文件,如果文件不存在则创建新文件

    FileMode.Truncate 指示操作系统应打开现有文件,并且清空文件内容

    文件共享方式:(FileShare)

    FileShare方式是为了避免几个程序同时访问同一个文件会造成异常的情况。

    文件共享方式包括四个:

    FileShare.None 谢绝共享当前文件

    FileShare.Read 充许别的程序读取当前文件

    FileShare.Write 充许别的程序写当前文件

    FileShare.ReadWrite 充许别的程序读写当前文件

    使用FileStream类创建文件流对象:

    FileStream(String 文件路径,FileMode 文件打开模式)

    FileStream(String 文件路径,FileMode 文件打开模式,FileAccess 文件访问方式)

    FileStream(String 文件路径,FileMode 文件打开模式,FileAccess 文件访问方式,FileShare 文件共享方式)

    使用File类来创建对象:(常用)

    自定义打开文件的方式:File.Open(String,FileMode);

    打开文件进行读取: File.OpenRead(String);

    打开文件进行写入: File.OpenWrite(String);

    注:

    对文件的读写操多不管代码有多少,无非就是下面的三步:

    1.创建文件读写流对象

    2.对文件进行读写

    3.关闭文件流

       

  • 相关阅读:
    Mac item 远程连接服务器
    搭建私人Git Server
    数据结构第三章小结
    第二章实践小结
    poj3617 Best Cow Line
    最长上升子序列问题
    Uva11450 Wedding shopping
    poj3050 hopscotch
    poj2718 Smallest Difference
    poj3669 Meteor Shower
  • 原文地址:https://www.cnblogs.com/erhanhan/p/8214685.html
Copyright © 2011-2022 走看看