當然了,可以使用:log4net 庫;
但目前該功能需求不需要用到這麼強大的日誌管理;直接寫檔案記錄;所以就寫了一個簡單的;
這是半成品,還可以用,還有地方可以最佳化;
但再最佳化前,可讀性比較好,我就上傳了:
using System;using System.Text;using System.IO;using System.Diagnostics;using System.Threading.Tasks;using System.Threading;using System.Runtime.InteropServices;namespace Testing{ public delegate bool ConsoleCtrlDelegate(int dwCtrlType); /// <summary> /// @author Jave.Lin /// @date 2013-12-11 /// </summary> public partial class Logger { [DllImport("kernel32.dll")] private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handlerRoutine, bool add); private const int CtrlCEvent = 0;//CTRL_C_EVENT = 0;//一個Ctrl+C的訊號被接收,該訊號或來自鍵盤,或來自GenerateConsoleCtrlEvent 函數 private const int CtrlBreakEvent = 1;//CTRL_BREAK_EVENT = 1;//一個Ctrl+Break訊號被接收,該訊號或來自鍵盤,或來自GenerateConsoleCtrlEvent 函數 private const int CtrlCloseEvent = 2;//CTRL_CLOSE_EVENT = 2;//當使用者系統關閉Console時,系統會發送此訊號到此 private const int CtrlLogoffEvent = 5;//CTRL_LOGOFF_EVENT = 5;//當使用者退出系統時系統會發送這個訊號給所有的Console程式。該訊號不能顯示是哪個使用者退出。 private const int CtrlShutdownEvent = 6;//CTRL_SHUTDOWN_EVENT = 6;//當系統將要關閉時會發送此訊號到所有Console程式 public static readonly object Locker = new object(); private static StreamWriter WRITER; // TODO : caches 可改用 StringBuilder 來最佳化 private static string ContinueWriteCaches; private static readonly Stopwatch Continue_WriteSw; private static int ContinueTime = 300; // 300毫秒以後,連續寫操作,都統一到一塊操作 private static int ContinueCountMax = 100; // 當連續寫操作次數上限到指定的數值後,都寫一次操作,之後的重新再計算 private static int ContinueCount = 0; private static string LoggerFileName; public static int AllWriteCount = 0; static Logger() { var nowDateTime = DateTime.Now; var dateTimeStr = nowDateTime.Year + "_" + nowDateTime.Month + "_" + nowDateTime.Day + "_" + nowDateTime.Hour + "_" + nowDateTime.Minute + "_" + nowDateTime.Second + "_" + nowDateTime.Millisecond; LoggerFileName = "Log/Logs_" + dateTimeStr + ".txt"; Continue_WriteSw = new Stopwatch(); if (SetConsoleCtrlHandler(new ConsoleCtrlDelegate(HandlerRoutine), true)) { Info("Set SetConsoleCtrlHandler success."); } else { Error("Set SetConsoleCtrlHandler Error."); } } private static bool HandlerRoutine(int ctrlType) { switch (ctrlType) { // src: //case CtrlCEvent: System.Console.WriteLine("Ctrl+C keydown"); break; //case CtrlBreakEvent: System.Console.WriteLine("Ctrl+Break keydown"); break; //case CtrlCloseEvent: System.Console.WriteLine("window closed"); break; //case CtrlLogoffEvent: System.Console.WriteLine("log off or shut down"); break; //case CtrlShutdownEvent: System.Console.WriteLine("system shut down"); break; //default: System.Console.WriteLine(ctrlType.ToString()); break; // new: //case CtrlCEvent: System.Console.WriteLine("Ctrl+C keydown"); break; //case CtrlBreakEvent: System.Console.WriteLine("Ctrl+Break keydown"); break; case CtrlCloseEvent: _WriteBuffer(); break; //case CtrlLogoffEvent: System.Console.WriteLine("log off or shut down"); break; //case CtrlShutdownEvent: System.Console.WriteLine("system shut down"); break; default: System.Console.WriteLine(ctrlType.ToString()); break; } return false; } private static void Write(string msg) { if (string.IsNullOrEmpty(msg)) { return; } lock (Locker) { if (ContinueWriteCaches == null) ContinueWriteCaches = msg + "\r\n"; else ContinueWriteCaches += msg + "\r\n"; if (Continue_WriteSw.IsRunning) { if (Continue_WriteSw.ElapsedMilliseconds > ContinueTime) { _WriteBuffer(); return; } } ++ContinueCount; if (ContinueCount > ContinueCountMax) { _WriteBuffer(); return; } if (!Continue_WriteSw.IsRunning) { Continue_WriteSw.Start(); } } } private static void _WriteBuffer() { if (ContinueWriteCaches != null) { if (!File.Exists(LoggerFileName)) { var dir = Directory.GetParent(LoggerFileName).FullName; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } } WRITER = new StreamWriter(LoggerFileName, true, Encoding.UTF8); WRITER.WriteLine(ContinueWriteCaches); WRITER.Flush(); WRITER.Close(); } Continue_WriteSw.Stop(); Continue_WriteSw.Reset(); ContinueWriteCaches = null; ContinueCount = 0; Interlocked.Increment(ref AllWriteCount); } } public partial class Logger { public static ConsoleColor S_InfoColor = ConsoleColor.White; public static ConsoleColor S_DebugColor = ConsoleColor.Green; public static ConsoleColor S_WarningColor = ConsoleColor.Yellow; public static ConsoleColor S_ErrorColor = ConsoleColor.Red; private static object _s_pLocker = new object(); // alwasy log public static void Info(string msg, params object[] ps) { if (ps != null && ps.Length > 0 ) { msg = string.Format(msg, ps); } _Write(S_InfoColor, "[Info]" + msg); } // remove log when debug complete. public static void Debug(string msg, params object[] ps) { if (ps != null && ps.Length > 0) { msg = string.Format(msg, ps); } _Write(S_DebugColor, "[Debug]" + msg); } // remove log when bug fixed. public static void Warning(string msg, params object[] ps) { if (ps != null && ps.Length > 0) { msg = string.Format(msg, ps); } _Write(S_WarningColor, "[Warning]" + msg); } // remove log when error fixed. public static void Error(string msg, params object[] ps) { if (ps != null && ps.Length > 0) { msg = string.Format(msg, ps); } _Write(S_ErrorColor, "[Error]" + msg); } private static void _Write(ConsoleColor color, string msg) { lock (_s_pLocker) { msg = DateTime.Now.ToString() + " " + msg; var srcColor = Console.ForegroundColor; Console.ForegroundColor = color; Console.WriteLine(msg); Console.ForegroundColor = srcColor; Write(msg); } } }}
測試調用:
for (int i = 0; i < 300; i++) { Logger.Debug("testsadfasdfasdf" + i); } Logger.Debug("Write Count : " + Logger.AllWriteCount); // 總調用IO寫的次數為:2次。。。但寫的內容次數就超過300