Cool_Breeze 发表于 2021-3-3 18:07

C# 学习笔记 <委托>,遍历目录文件大小 过滤保存日志

本帖最后由 Cool_Breeze 于 2021-3-3 19:20 编辑

using System;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;

class DelegateExtension
{
    // 委托类型声明 返回值类型 string 类型名 MyDelegate 参数 digits 类型为 int
    public delegate string MyDelegate(int digits);
   
    static void Main()
    {
      // Test test = new Test();
      
      // 自定义委托
      // MyDelegate fu1 = new MyDelegate(test.fun1);
      // MyDelegate fu2 = new MyDelegate(Test.fun2);
      // MyDelegate fu1 = test.fun1;
      // MyDelegate fu2 = Test.fun2;
      
      // 系统封装好的不带返回值委托类
      // Action<string> fu3;
      // fu3 = test.fun3;
      
      // 系统封装好的带返回值的委托类
      // 方法返回值类型放在Func最后面
      // Func<int, string> fu1 = test.fun1;
      // Func<int, string> fu2 = Test.fun2;
      
      // Console.WriteLine(fu1(2));
      // Console.WriteLine(fu2(20));
      // fu3("GIN");
      
      string logPath = @"D:\GIN\c#\Exercise\log.log";
      // 实例默认输出至logPath
      FileLogger fileLogger = new FileLogger(logPath);
      
      
      // Console.WriteLine("日志级别:{0}", Logger.LogLevel);
      // Logger.LogMessage(Severity.Error, "Logger", "ERROR");
      // Logger.LogMessage(Severity.Warning, "Logger", "Warning");
      // 等级低于设置级别,不打印
      // Logger.LogMessage(Severity.Information, "Logger", "Information");
      
      // 卸载LogPath.LogMessage, 将不会输出之文本
      // fileLogger.DetachLog();
      // Logger.LogLevel = Severity.Information;
      // Console.WriteLine("日志级别:{0}", Logger.LogLevel);
      // Logger.LogMessage(Severity.Information, "Logger", "Information");
      
      FileInformation target = new FileInformation(@"D:\");
      
      // 修改日志级别
      Logger.LogLevel = Severity.Information;
      Console.WriteLine("日志级别:{0}", Logger.LogLevel);
      
      // 不在控制台输出
      // 从多播委托中卸载控制台输出
      Logger.WriteMessage -= Console.WriteLine;
      
      // 扫描之前设置一下过滤文件的大小
      // 文件小于 1M 的将被记录
      target.filterFileSizeKB = 1024;
      // 开始扫描
      target.StartScan();
      
    }
   
    // logger 输出级别
    public enum Severity
    {
      Verbose,
      Trace,
      Information,
      Warning,
      Error,
      Critical
    }
   
    // 日志输出
    public static class Logger
    {
      // 静态类中也不能出现实例的字段成员
      // 静态类的字段需要在编译前赋值, 不能在运行时赋值, 除了它的属性
      // 消息处理处理委托,参数为 string
      
      // 默认输出至控制台
      public static Action<string> writeMessage = Console.WriteLine;
      public static Action<string> WriteMessage{get{return writeMessage;} set {writeMessage = value;}}
      
      // 日志输出等级设置
      private static Severity logLevel = Severity.Warning;
      
      // 设置字段属性
      public static Severity LogLevel{get{return logLevel;} set {logLevel = value;}}
      
      
      // 判断输入日志是否满足日志输出等级 (需要三个参数)
      public static void LogMessage(Severity s, string component, string msg)
      {
            // 设置日志级别小于 logLevel 级别跳过
            if (s < logLevel)
            {
                return;
            }
            
            // 设置日志级别大于等于 Warning 将在控制台输出
            // 这里有个 BUG 没有检查多播链中是否已经存在这个方法
            if (s >= Severity.Warning)
            {
                writeMessage += Console.WriteLine;
                writeMessage(String.Format("{0}\t{1}\t{2}", DateTime.Now, component, msg));
                writeMessage -= Console.WriteLine;
                return;
            }
            
            // 调用日志输出方法
            // String.Format 将返回一个字符串,传入 writeMessage 委托的方法
            writeMessage(String.Format("{0}\t{1}\t{2}", DateTime.Now, component, msg));
      }
      
    }
   
    // 输出日志到本地文件
    public class FileLogger
    {
      private readonly string logPath;
      public FileLogger(string path)
      {
            logPath = path;
            // 加入 追加模式写入文本方法(多播委托)
            Logger.WriteMessage += LogMessage;
      }
      
      // 追加模式写入文本 utf-8
      public void LogMessage(string msg)
      {
            try
            {
                using (var log = File.AppendText(logPath))
                {
                  log.WriteLine(String.Format("{0}", msg));
                  log.Flush();
                }
            }
            catch
            {
                  Console.WriteLine("记录日志到 {0} 文件中失败!", logPath);
            }
      }
      
      // 卸载 LogMessage
      public void DetachLog()
      {
            Logger.writeMessage -= LogMessage;
      }
    }
   

    // 文件信息扫描
    public class FileInformation
    {
      // 扫描文件夹路径
      public string TargetDirectory{get;set;}
      
      public FileInformation(string dir)
      {
            this.TargetDirectory = dir;
      }
      
      // 这个可以设置成其他容量,需要转换
      // 设置过滤文件大小
      public float filterFileSizeKB = 0;
      public float FilterFileSizeKB
      {
            get
            {
                return filterFileSizeKB;
            }
            set
            {
                this.filterFileSizeKB = value;
            }
      }
      
      // 指定不可访问的目录
      public List<string> skipList = new List<string>{@"$RECYCLE.BIN", @"System Volume Information"};
      
      // value 的值是 List<string> 类型
      public List<string> SkipList
      {
            get
            {
                return this.skipList;
            }
            set
            {
                // 这里可以检查一下列表里面是否已经存在
                foreach (var str in value)
                {
                  // 不存在,则加入
                  if (this.skipList.IndexOf(str) == -1)
                        this.skipList.Add(str);
                }
            }
      }
      
      public bool StartScan()
      {
            DirectoryInfo dir;
            // 处理报错
            try
            {
                dir = new DirectoryInfo(this.TargetDirectory);      
                decimal count = 0; // 文件计数
                bool flag = false;
                foreach (var each in dir.GetDirectories())
                {
                  flag = false;
                  // 查询是否包含不可访问目录
                  foreach (var sikp in this.skipList)
                  {
                        if (each.FullName.Contains(sikp))
                        {
                            flag = true;
                            // 开启记录日志
                            Logger.LogMessage(Severity.Warning, "FileInformation", String.Format("{0}跳过指定目录:{1}", DateTime.Now, each.FullName));
                            break;
                        }
                  }
                  
                  if (flag) continue;
                  
                  DirectoryInfo eachDir = new DirectoryInfo(each.FullName);
                  // 在搜索操作中包括当前目录和所有它的子目录。 此选项在搜索中包括重解析点,比如安装的驱动器和符号链接。
                  foreach (System.IO.FileInfo fi in eachDir.GetFiles("*.*", System.IO.SearchOption.AllDirectories))
                  {
                        count++;
                        // 这里只记录文件大小 小于 指定文件大小
                        // 其他的还可以增加
                        if (fi.Length < this.FilterFileSizeKB)
                            // 开启记录日志
                            Logger.LogMessage(Severity.Information, "FileInformation", String.Format("{0},{1},{2}",count, fi.FullName, fi.Length));
                  }
                }
            }
            catch (Exception err)
            {
                Logger.LogMessage(Severity.Error, "FileInformation", err.Message);
                return false;
            }
            // 暂且返回真
            return true;
      }
      
      // 加入日志
      public void FromLog(FileLogger obj)
      {
            Logger.writeMessage += obj.LogMessage;
      }
      
      // 移除日志
      public void DetachLog(FileLogger obj)
      {
            Logger.writeMessage -= obj.LogMessage;
      }
    }
   
   
    public class Test
    {
      public void fun3(string name)
      {
            MessageBox.Show(String.Format("Hello {0} !", name));
      }
      
      public string fun1(int digits)
      {
            if (digits > 10)
            {
                return String.Format("{0} > 10", digits);
            }
            else
            {
                return String.Format("{0} < 10", digits);
            }
      }
      
      public static string fun2(int digits)
      {
            if (digits > 10)
            {
                return "GEQ";
            }
            else
            {
                return "LEQ";
            }
      }
    }
}

smilencetion 发表于 2021-3-3 18:47

看书还是视频?

Cool_Breeze 发表于 2021-3-3 18:56

本帖最后由 Cool_Breeze 于 2021-3-3 18:58 编辑

smilencetion 发表于 2021-3-3 18:47
看书还是视频?
书看的官方文档,视频看的是刘铁锰的,视频b站有,33集 那个是完整的(从 油管搬下来的)

C# 入门了,再学窗口(好像也可以一起学{:1_900:})

liu1615114899 发表于 2021-3-3 18:58

学习了,谢谢楼主

alphasong 发表于 2021-3-3 19:15

正在学C#,用得上,保存下来学习

chenshi571 发表于 2021-3-16 12:48

刚刚开始学,这个很有用

xingxing901015 发表于 2021-3-16 13:45

刚开始学,不知道能学的咋样,过来膜拜膜拜各位大佬

huamu 发表于 2021-3-18 03:20

准备学一学

Laugher_ 发表于 2021-3-22 15:42

Func和Action
页: [1]
查看完整版本: C# 学习笔记 <委托>,遍历目录文件大小 过滤保存日志