wanshenmean
2026-03-13 0dbc8273bdfbcabcc4b770546245f6b17d787de9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core.Helper;
 
namespace WIDESEAWCS_Core.LogHelper
{
    public class LoggerHelper
    {
        // 读写锁,确保多线程环境下日志写入的线程安全
        static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
 
        // 日志文件夹路径
        static string folderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Log");
 
        // 记录日志的队列
        static Queue<string> logQueue = new Queue<string>();
 
        static LoggerHelper()
        {
            try
            {
                if (!Directory.Exists(folderPath))
                {
                    Directory.CreateDirectory(folderPath);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="filePath"></param>
        public static void WriteError(Exception ex, string filePath = "")
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("错误信息:");
            builder.Append(ex.Message);
            builder.Append(Environment.NewLine);
            builder.Append("错误源:");
            builder.Append(ex.Source);
            builder.Append(Environment.NewLine);
            builder.Append("错误堆栈:");
            builder.Append(ex.StackTrace);
            builder.Append(Environment.NewLine);
            builder.Append("错误类型:");
            builder.Append(ex.GetType().ToString());
            builder.Append(Environment.NewLine);
            builder.Append("错误方法:");
            builder.Append(ex.TargetSite?.ToString());
            builder.Append(Environment.NewLine);
            builder.Append(Environment.NewLine);
 
            WriteLogToFile($"Error_", builder.ToString(), filePath);
        }
 
        /// <summary>
        /// 将日志内容写入指定文件
        /// </summary>
        /// <param name="fileName">日志文件名</param>
        /// <param name="log">要记录的日志内容</param>
        /// <remarks>
        /// 该方法会确保线程安全地写入日志,若目录不存在会自动创建,
        /// 日志内容会自动添加时间戳并追加到文件末尾
        /// </remarks>
        public static void WriteLogToFile(string fileName, string log, string filePath = "")
        {
            try
            {
                // 进入写锁
                LogWriteLock.EnterWriteLock();
 
                string path = string.IsNullOrEmpty(filePath) ? folderPath : filePath;
 
                // 如果文件夹不存在,则创建文件夹
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                // 获取日志文件路径
                string logFilePath = Path.Combine(path, GetLastAccessFileName(fileName, path));
                // 获取当前时间
                DateTime now = DateTime.Now;
                // 构造日志内容
                string logContent = $"【{now}】{Environment.NewLine}{log}";
 
                // 将日志内容追加到日志文件中
                File.AppendAllText(logFilePath, logContent);
 
                WriteCompleted();
            }
            catch { }
            finally
            {
                // 退出写锁
                LogWriteLock.ExitWriteLock();
            }
        }
        static int size = 10 * 1024 * 1024;
 
        /// <summary>
        /// 获取最后一个可用的日志文件名
        /// </summary>
        /// <param name="fileName">日志文件基础名称</param>
        /// <returns>如果存在未达到大小限制的日志文件则返回该文件名,否则返回基于当前时间的新日志文件名</returns>
        /// <remarks>
        /// 该方法会遍历所有已存在的日志文件,返回第一个文件大小未超过限制的文件名。
        /// 如果没有符合条件的文件,则生成一个以当前时间命名的新日志文件名。
        /// </remarks>
        private static string GetLastAccessFileName(string fileName, string path)
        {
            foreach (var m in GetExistLogFileNames(fileName, path))
            {
                FileInfo fileInfo = new FileInfo(m);
                if (fileInfo.Length < size)
                {
                    return m;
                }
            }
 
            // 返回一个新的默认当前时间的日志名称
            return $@"{fileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.log";
        }
 
        /// <summary>
        /// 获取指定文件名模式的所有日志文件
        /// </summary>
        /// <param name="fileName">日志文件名前缀</param>
        /// <returns>匹配文件名模式的所有日志文件路径数组</returns>
        private static string[] GetExistLogFileNames(string fileName, string path)
        {
            string[] fileNames = Directory.GetFiles(path, fileName + "*.log");
            return fileNames;
        }
 
        private static string[] GetExistLogFileNames()
        {
            if (!string.IsNullOrEmpty(folderPath))
                return Directory.GetFiles(folderPath, "Error_*.log");
            else
                return new string[] { };
        }
 
        private static int controlFileQuantity = 100;
 
        protected static void WriteCompleted()
        {
            if (controlFileQuantity > 1)
            {
                try
                {
                    string[] files = GetExistLogFileNames();
                    if (files.Length > controlFileQuantity)
                    {
                        List<FileInfo> fileInfos = new List<FileInfo>();
                        for (int i = 0; i < files.Length; i++)
                        {
                            fileInfos.Add(new FileInfo(files[i]));
                        }
 
                        fileInfos.Sort(new Comparison<FileInfo>((m, n) =>
                        {
                            return m.CreationTime.CompareTo(n.CreationTime);
                        }));
 
                        for (int i = 0; i < fileInfos.Count - controlFileQuantity; i++)
                        {
                            File.Delete(fileInfos[i].FullName);
                        }
                    }
                }
                catch
                {
 
                }
            }
        }
    }
}