我在「利用StreamWriter 資料流I/O 寫成檔案」這篇文章寫了一個自已學習的歷程
主題雖然是使用System.IO類別下的方法,但是具體而微,System.IO命名空間下,除了有提供讀寫檔案和資料流的類別外,就是基本檔案、目錄管理的類別。方法都是大同小異…
這次的程式碼範例,我就特別針對「將內容寫進新建的文字檔」「開啟檔案並讀取內容」「將內容附加到既有的文字檔」這三個功能,分別寫了System.IO.Stream 和System.IO.File 二種版本,用這二種類別都可以完成,邏輯上是一樣的,只不過要使用自已類別下的Method方法來達成目的而已。
頁面上的佈置很簡單,一個TextBox、三顆功能按鈕
以下提供File和Stream二種類別的寫法
使用System.IO.StreamReader / StreamWriter 的寫法
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load Me.ButtonIOWirte.Text = "將內容寫進新建的文字檔" Me.ButtonIORead.Text = "開啟檔案並讀取內容" Me.ButtonIOAppend.Text = "將內容附加到既有的文字檔" End Sub Protected Sub ButtonIOWirte_Click(sender As Object, e As System.EventArgs) Handles ButtonIOWirte.Click FileManager.CreateTextFile(Page, Server.MapPath("DnowLog/AspNet51.txt"), Me.TextBoxIO.Text) End Sub Protected Sub ButtonIORead_Click(sender As Object, e As System.EventArgs) Handles ButtonIORead.Click FileManager.OpenFileRead(Page, MapPath("DnowLog/AspNet51.txt")) End Sub Protected Sub ButtonIOAppend_Click(sender As Object, e As System.EventArgs) Handles ButtonIOAppend.Click FileManager.CreatTextAppend(Page, MapPath("DnowLog/AspNet51.txt"), Me.TextBoxIO.Text) End Sub MSDN**************************************************** 'http://msdn.microsoft.com/zh-tw/library/system.io.file.aspx (建立文字檔 System.IO.File) '*************************************************************************************** Public Shared Sub CreateTextFile(ByVal WebForm As System.Web.UI.Page, ByVal path As String, ByVal filebody As String) If System.IO.File.Exists(path) = False Then 'Using sw As System.IO.StreamWriter = System.IO.File.CreateText(path) Using sw As New System.IO.StreamWriter(path, True) sw.Write(filebody) sw.Flush() End Using End If End Sub ' 開啟檔案並讀取內容 參考自MSDN********************************************************* ' http://msdn.microsoft.com/zh-tw/library/system.io.file.aspx (建立文字檔 System.IO.File) ' http://msdn.microsoft.com/zh-tw/library/db5x7c0d.aspx (讀取文字檔 HOW TO:從檔案讀取文字) ' ****************************************************************************************** Public Shared Sub OpenFileRead(ByVal WebForm As System.Web.UI.Page, ByVal path As String) Try Using sr As System.IO.StreamReader = System.IO.File.OpenText(path) ' 第一種讀取內容的方法============================================= 'Dim sb As New StringBuilder() 'sb.AppendLine(sr.ReadToEnd) 'CType(WebForm.FindControl("TextBox1"), TextBox).Text = sb.ToString '=================================================================== ' 第二種讀取內容的方法============================================ 'Dim sb As New StringBuilder() 'Do While sr.Peek() >= 0 ' sb.AppendLine(sr.ReadLine()) 'Loop 'CType(WebForm.FindControl("TextBox1"), TextBox).Text = sb.ToString '================================================================== ' 第三種讀取內容的方法============================================= Dim sb As New StringBuilder() Dim line As String Do line = sr.ReadLine() If line IsNot Nothing Then sb.AppendLine(line) End If Loop Until line Is Nothing CType(WebForm.FindControl("TextBoxIO"), TextBox).Text = sb.ToString '=================================================================== End Using Catch e As Exception CType(WebForm.FindControl("TextBoxIO"), TextBox).Text = e.Message & "無法開啟指定檔案,或是無法正確讀取檔案內容,請洽詢管理員" End Try End Sub ' 將內容附加到既有的文字檔,參考自**************************************************************** ' http://msdn.microsoft.com/zh-tw/library/3zc0w663.aspx (HOW TO:開啟並附加至記錄檔) ' ******************************************************************************************* Public Shared Sub CreatTextAppend(ByVal WebForm As System.Web.UI.Page, ByVal path As String, ByVal filebodyappend As String) Using sw As New System.IO.StreamWriter(path, True) sw.WriteLine(filebodyappend) End Using End Sub End Class
使用System.IO.File.ReadAllText / WriteAllText 的寫法
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load Me.ButtonIOWirte.Text = "將內容寫進新建的文字檔" Me.ButtonIORead.Text = "開啟檔案並讀取內容" Me.ButtonIOAppend.Text = "將內容附加到既有的文字檔" End Sub Protected Sub ButtonIOWirte_Click(sender As Object, e As System.EventArgs) Handles ButtonIOWirte.Click FileManager.CreateTextFile(Page, Server.MapPath("DnowLog/AspNet52.txt"), Me.TextBoxIO.Text) End Sub Protected Sub ButtonIORead_Click(sender As Object, e As System.EventArgs) Handles ButtonIORead.Click FileManager.OpenFileRead(Page, MapPath("DnowLog/AspNet52.txt")) End Sub Protected Sub ButtonIOAppend_Click(sender As Object, e As System.EventArgs) Handles ButtonIOAppend.Click FileManager.CreatTextAppend(Page, MapPath("DnowLog/AspNet52.txt"), Me.TextBoxIO.Text) End Sub Public Class FileManager ' 將文字寫進新建的文字檔 參考自MSDN**************************************************** 'http://msdn.microsoft.com/zh-tw/library/ms143368.aspx (File.ReadAllText 方法) '*************************************************************************************** Public Shared Sub CreateTextFile(ByVal WebForm As System.Web.UI.Page, ByVal path As String, ByVal filebody As String) If System.IO.File.Exists(path) = False Then System.IO.File.WriteAllText(path, filebody) End If End Sub ' 開啟檔案並讀取內容 參考自MSDN********************************************************* 'http://msdn.microsoft.com/zh-tw/library/ms143368.aspx (File.ReadAllText 方法) ' ****************************************************************************************** Public Shared Sub OpenFileRead(ByVal WebForm As System.Web.UI.Page, ByVal path As String) Try CType(WebForm.FindControl("TextBoxIO"), TextBox).Text = System.IO.File.ReadAllText(path) Catch e As Exception CType(WebForm.FindControl("TextBoxIO"), TextBox).Text = e.Message & "無法開啟指定檔案,或是無法正確讀取檔案內容,請洽詢管理員" End Try End Sub ' 將內容附加到既有的文字檔,參考自**************************************************************** ' http://msdn.microsoft.com/zh-tw/library/3zc0w663.aspx (HOW TO:開啟並附加至記錄檔) ' ******************************************************************************************* Public Shared Sub CreatTextAppend(ByVal WebForm As System.Web.UI.Page, ByVal path As String, ByVal filebodyappend As String) System.IO.File.AppendAllText(path, Environment.NewLine & filebodyappend) End Sub End Class End Class
在完成一個功能的使用,有時候開發時間所限
我們需要先求有再求好,在最短的時間內達到目的
這篇文章是已經有要求更好,主要是在研究
這篇文章主要就是在討論
System.IO.StreamReader/StreamWriter 和 System.IO.File.ReadAllText/WriteAllText
既然都可以完成一樣的功能
那麼為什麼不整合在一起就好了
二者之間有沒有什麼不一樣
我想就我自已實作後分享一下兩者之間的不同
1、二者的類別不同
如下圖,以StreamReader/ReadAllText 來看
StreamReader/StreamWriter 本身是類別
ReadAllText/WriteAllText 是System.IO.File下的方法
所以很明顯的二者的類別不同…廢話
這樣的差別就可以概略知道,一定是架構大一點的或是有特定目的之下才會「自成一類」,可以猜的到單就「存取檔案」的功能來說,身為類別的「StreamReader/StreamWriter 」肩負著比較多的功能。
比方說,我要把資料寫入一個檔案,寫入前要先檢查檔案是否存在
System.IO.StreamWriter 的寫法,用自已類別下的方法可以解決:
Using sw As New System.IO.StreamWriter( "C:/Document/Dnowba.txt" , True)
sw.Write( "這是測試文字" )
End Using
System.IO.File.WriteAllText 的寫法可能就要用到「其他的方法」:
If System.IO.File.Exists( "C:/Document/Dnowba.txt" ) = False Then
System.IO.File.WriteAllText("C:/Document/Dnowba.txt", "這是測試文字")
End If
那麼也許我們可以說System.IO.StreamWriter 和 System.IO.File.WriteAllText 在「功能」上並沒有什麼差異。StreamWriter 不過是包裝比較精美的程式。是不是這樣呢?也許我們再從實作上觀察一下…
我們在呼叫方法之後,觀察一下他們就方法來說的話,WriteAllText 的方法多載(overload,又叫重載、覆載) 有二種。
但是在StreamWriter上的方法多載數量高達17個
你說包裝精不精美?System.IO.StreamReader/StreamWriter 在檔案存取的應用上應當是可以更靈活富變化。
不過我們也可以看到System.IO.File 底下是有其他的方法的,雖然不一定是針對檔案存取功能…但其他功能的支援性是比較足的。
所以在檔案存取時,用哪個方法比較好?沒有一定。
如果你要針對檔案內容做比較複雜的運用的話,用System.IO.StreamWriter
如果你只是簡單的使用 (像上面) ,那麼用System.IO.File.WriteAllText 就措措有餘
我再舉個例子說明…
System.IO.StreamWriter 的寫法,多載的方法下提供了可以format string的參數:
Using sw As New System.IO.StreamWriter( "C:/Document/Dnowba.txt" , True)
sw.Write( "本文章作者{0},發佈日期{1}","DNOWBA",DateTime.Now )
End Using
System.IO.File.WriteAllText 下要把字串格式化,就只能透過最原始的串接:
If System.IO.File.Exists( "C:/Document/Dnowba.txt" ) = False Then
System.IO.File.WriteAllText("C:/Document/Dnowba.txt", "本文作者DNOWBA,
發佈日期" & DateTime.Now )
End If
2 、 類別宣告方式不同
System.IO.StreamReader/StreamWriter 是Instance Class
System.IO.File 是 Static Class…
所以在 System.IO.StreamReader/StreamWriter 使用時都需要「實體化」
而靜態類別的成員則不需要透過類別的執行個體就可以直接存取
靜態宣告和非靜態宣告的差別當然不只這樣
最常被討論是用靜態宣告和非靜態宣告的效能上的差別
靜態宣告在一載入程式時,整個class就會被加載到執行緒
非靜態宣告只有當你「new」的時候才會生效,而變數使用完畢後就可以丟掉
效能問題不是我這個後生小輩可以討論的
不過看起來的確是靜態宣告比較耗費資源
所以用非靜態宣告的System.IO.StreamReader/StreamWriter 比較好?其實這也沒有一定
如果你在這個webform主要的功能就是讀寫檔案,需要不斷不斷的使用的話,那麼開開關關的的非靜態宣告方式就很沒有必要,資源在開關之間也是會消耗的。
3、應用時機不同
我在使用Framework的時候,常常會發現在裡頭有很多類似的情形
「二個函式都可以完成某種特定功能,為什麼不要合併在一起呢?」
我覺得可以合理懷疑一件事
Framework 是一個巨大的架構,架構設計師應該不只一位,包括架構師在內,在不同架構師底下的團隊也不大可能每個人都對Framework 都瞭若指掌,再加上開發的時間點不一致的情況下,那麼
會不會在開發 System.IO.File 類別下有關檔案讀取功能的時候,架構師渾然不知Framework 裡早就有很棒的System.IO.StreamReader/StreamWriter 呢?
(我覺得這個可能性很大…)
如果已經知道有 System.IO.StreamReader/StreamWriter ,會不會在開發 System.IO.File 下的檔案讀取功能時,偷偷的用了 System.IO.StreamReader/StreamWriter ?
( 如果我能打開它的.dll 組態設定檔,也許就能查證了)
不過前面提到了他們在不同類別底下
同母(Framework)異父(Class) 的情況下,當然長相 (方法) 也還是有分別,對我來說:
檔案的應用在程式設計上是重點:
在WinForm程式偏重在檔案的管理,例如對檔案的刪除、複製、移動。
在WebForm上則偏重在讀取後匯入、寫進後匯出檔案的功能。
偶有所得
這一次的程式碼中是在研究中誕生
本來是範例是直接寫在事件常式中
寫著寫著,覺得二者之間互有異同
所以就嘗試使用自訂類別
讓程式間能夠互通有無
我想這也是寫程式的人最想要完成的一件事
1、在webform裡完成某個功能 | 用不同的變數/方法,寫在各自的事件常式中 |
2、在同一個webform互相調用 | 用Function 或 Sub副程式,把可以共用的程式整合,讓其他事件常式可以反覆調用 |
3、同一個網站的webform | 集結了許多的Function 或 Sub副程式後,再把共用的功能包成不同或同一個Class,讓專案中的其他webform引用 |
4、不同網站/專案 | 把class編譯成DLL檔,可以將這個.net檔「加入參考」 |
5、分散式的網站 | 透過Web Service 或是 WCF |
這次的程式碼就是在第2階段啦
雖然有點生硬,不過還算堪用
分享給大家。
沒有留言:
張貼留言