記錄日志,一方面可以把日志寫入系統的日志存儲中,可在“事件查看器”窗口中查看;如果不喜歡寫到系統的日志文件中,也可以寫到自己定義的文件中。
其實,日志文件就是文本文件,可能有朋友會想到用寫入文本文件的方式來寫日志。當然,這樣做也是可以的,不過,.NET 類型庫提供了兩個專用記錄信息的類。
Debug 類大家都很熟悉,就是可以在VS的“輸出”窗口寫入調試信息,另外,有一個跟Debug很像的類——Trace。Debug通常只會在調試版本中使用,Trace既可以在調試版本中用,也可以用於發布(Release)版本。
下面以Write方法為例,看看Debug類和Trace類的定義有什麼不同。
// Debug [ConditionalAttribute("DEBUG")] public static void Write( Object value ) // Trace [ConditionalAttribute("TRACE")] public static void Write( Object value )
ConditionalAttribute用於指定一個條件,當條件中給出的條件編譯符號存在時才會執行。DEBUG和TRACE這兩個符號可以在編譯的時候指定,也可以在VS項目屬性中指定。
接下來我們了解一下監聽器,它的公共基類是TraceListener,而Debug和Trace類都有一個Listeners集合,可以添加從TraceListener派生的任意實例。即使我們沒有在代碼中向Listeners集合添加元素,在應用程序運行時,它會自動添加一個默認的監聽器,類型為DefaultTraceListener。
好了,前面都是F話,只是給大家娛樂的,說到了DefaultTraceListener,就進入本文主題了,看一下,這個類是不是有個屬性叫LogFileName?這就對了,只要把日志文件的相對路徑或絕對路徑賦給它就行了,日志文件可以不存在,但目錄應該是存在的。
來來來,咱們來練習一下。
// 從 Listeners 集合中找出默認監聽器 DefaultTraceListener listener = Trace.Listeners["Default"] as DefaultTraceListener; // 指定日志文件 if (listener != null) { listener.LogFileName = "MyApp.log"; } // 測試寫入 Trace.WriteLine("今天天氣很好。"); Trace.WriteLine("明天天氣依舊地熱。"); Trace.WriteLine(DateTime.Today.ToLongDateString());
剛剛說過,默認情況下,Listeners集合中會有一個DefaultListener監聽器,而且它的Name屬性為“Default”,因此,我們按照名稱就可以把它取出來,然後設置它的LogFileName屬性,這裡我用的是相對路徑,即創建的日志文件位於可執行文件相同的目錄下。
使用Trace類而不用Debug類,是因為Trace可以在調試版本中用,也可以在發布版本中用。從運行過程來看,跟蹤信息既會出現在“輸出”窗口中,也會同時寫入前面指定的日志文件中。
待上面示例運行後,再到程序目錄下,用記事本打開日志文件,就能看到記錄的信息了。
要是你比較不喜歡用默認的監聽器,還可以先把Listeners集合清空,然後Add一個別的監聽器,除了DefaultTraceListener,還有TextWriterTraceListener、XmlWriterTraceListener等,它們的繼承關系就不說了,自己看文檔。
下面我們來用TextWriterTraceListener來寫入日志文件。
static void Main(string[] args) { // 清空監聽器集合 Trace.Listeners.Clear(); // 加入新的監聽器 TextWriterTraceListener listener = new TextWriterTraceListener("app.log"); Trace.Listeners.Add(listener); // 測試寫入信息 Trace.WriteLine("a - b - c"); Trace.WriteLine(DateTime.Now.ToLongTimeString()); Console.Read(); // 刷新流並關閉 Trace.Flush(); listener.Close(); }
這裡要注意,TextWriterTraceListener類用完後要調用Close或Flush方法,或者Dispose方法,又或者調用Trace類的Flush方法,反正你任選一種方案吧。因為需要這樣做之後,數據才會最後寫入到文件中,不然,文件是空白的。
運行示例過後,再打開app.log文件,得到在下文本。
有沒有發現,配置日志文件路徑寫在代碼中不太好玩,因為更改路徑和文件名後就要重新編譯,不如,考慮寫在配置文件中吧。
打開配置文件,輸入以下內容:
<configuration> …… <system.diagnostics> <trace autoflush="true"> <listeners> <clear/> <add name="test" type="System.Diagnostics.TextWriterTraceListener" initializeData="D:\TheApp.log"/> </listeners> </trace> </system.diagnostics> </configuration>
下面給大伙分析一下這配置文件的規律。
第一,你想想,我們剛剛講的那些類都在哪個命名空間下?對了,System.Diagnostics,所以,對應地,在配置節中名為system.diagnostics。
第二、Trace是與跟蹤信息有關,所以下一個節點是trace。
第三、前面我說過,Trace和Debug類都有一個Listeners集合,用來放監聽器,是吧,所以下一子級就需要一個listeners節點。
第四、listeners是個集合吧,所以它應該可以添加元素,刪除元素,清除元素。這就對了,add用來添加監聽器;remove用來刪除監聽器;clear就是清空集合,等於調用Clear方法。
所以,上面配置中,clear就是把合集先清空,然後用add來加元素。name指定監聽器的名字,這個你可以自己取,最好不要叫“Default”,剛說過了嘛,默認的監聽器叫“Default”,你沒必要非要用這個名字,你可以叫它“孫悟空”。
type指定監聽器的類型,一定要包含命名空間和類名,程序集中的version和pubKey這些可以不寫。
initializeData是傳遞給TextWriterTraceListener類構造函數的數據,對它來說,應該傳入日志文件路徑。我這裡就把它存到D盤下面,你可以根據你的實際情況來定。
注意:trace元素的autoflush設為true,推薦這麼干,這樣會自動調用Flush方法,從而讓數據及時寫入日志文件。
以後,你想更改日志文件路徑,只要改改配置文件就行了,不必重新編譯代碼。
現在,這個配置你會寫了吧,結構都懂了吧,而且VS還有智能提示的。要是這樣你還不會寫,那老周只好投降了。
好,配置弄好了,咱們寫幾句代碼耍耍。
static void Main(string[] args) { Trace.WriteLine("好玩。"); Trace.WriteLine("再寫一行。"); Trace.WriteLine("Write a new line again."); }
運行應用程序,運行完後,打開日志文件,會看到這樣:
好了,今天的任務完成了。
經過黨組織討論決定,由於本文的示例代碼實在太簡單了,本文不提供示例源碼文件。