第7章 Web伺服器檔案與XML文件的處理 7-1 System.IO名稱空間的基礎 7-2 伺服器的資料夾與檔案操作 7-3 文字檔案讀寫、搜尋和取代 7-4 二進位檔案的處理 7-5 XML文件的處理
7-1 System.IO名稱空間的基礎 7-1-1 在Web網站儲存資料的方式 7-1-2 System.IO名稱空間 7-1-3 取得伺服端檔案或資料夾的路徑
7-1-1 在Web網站儲存資料的方式 在ASP.NET程式建立的Web網站,可以需要儲存一些暫時或永久的資料,以幫助Web網站的瀏覽和ASP.NET程式的執行,如下所示: 使用文字檔案儲存:將資料儲存成Web伺服器的文字檔案。在ASP.NET程式是使用System.IO名稱空間的類別來處理文字檔案的資料。 使用XML文件儲存:將資料儲存成XML文件。ASP.NET程式是使用System.Xml名稱空間的類別來處理XML文件。 使用資料庫儲存:將資料儲存在伺服端的資料庫系統,也就是所謂的網頁資料庫,在第8~9章筆者將詳細討論此部分。
7-1-2 System.IO名稱空間 System.IO名稱空間提供檔案和資料夾處理的相關類別。其主要的類別,如下表所示:
7-1-3 取得伺服端檔案或資料夾的路徑-取得ASP.NET程式的實際路徑 ASP.NET程式檔案所在的虛擬目錄,可以使用ServerVariables集合物件的PATH_INFO來取得,如下所示: Request.ServerVariables("PATH_INFO") 程式碼取得目前執行ASP.NET檔案的虛擬目錄。只需配合Server.MapPath()方法,就可以轉換成實際路徑,如下所示: path1 = Server.MapPath( _ Request.ServerVariables("PATH_INFO"))
7-1-3 取得伺服端檔案或資料夾的路徑-取得指定目錄的實際路徑 同樣方法,可以取得指定虛擬目錄的實際目錄。例如:取得Web伺服器主目錄的實際路徑,如下所示: path2 = Server.MapPath("/") 至於取得指定虛擬目錄的實際路徑,如下所示: path3 = Server.MapPath("/Ch07")
7-2 伺服器的資料夾與檔案操作 7-2-1 顯示伺服器的磁碟清單 7-2-2 顯示資料夾清單和相關資訊 7-2-3 資料夾的處理 7-2-4 顯示檔案清單和資訊 7-2-5 檔案處理
7-2-1 顯示伺服器的磁碟清單 我們可以使用Directory類別的GetLogicalDrives()方法,來取得所有Web伺服器的邏輯磁碟清單,如下所示: Dim arrDrives() As String = Directory.GetLogicalDrives() 程式碼取得磁碟機清單的字串陣列後,就可以使用迴路顯示陣列內容,也就是所有磁碟機代碼,如下所示: For i = 0 To arrDrives.Length - 1 Response.Write(arrDrives(i) & " ") Next
7-2-2 顯示資料夾清單和相關資訊-顯示資料夾下子資料夾清單1 在DirectoryInfo類別的GetDirectories()方法可以取得資料夾清單,如下所示: Dim dInfo As DirectoryInfo = _ new DirectoryInfo(path) Try Dim subDirs() As DirectoryInfo = _ dInfo.GetDirectories() ……… Catch ex As DirectoryNotFoundException s = "<font color=red>" & ex.Message & _ "</font>" End Try
7-2-2 顯示資料夾清單和相關資訊-顯示資料夾下子資料夾清單2 程式碼建立DirectoryInfo物件後,使用GetDirectories()方法取得子資料夾清單的DirectoryInfo物件陣列,然後就可以使用迴路顯示子資料夾清單,如下所示: For i = 0 To subDirs.Length - 1 s &= "<tr><td>" & subDirs(i).Name & _ "</td>" Next 程式碼在取得指定DirectoryInfo物件後,使用Name屬性取得資料夾名稱。
7-2-2 顯示資料夾清單和相關資訊-DirectoryInfo物件的屬性
7-2-3 資料夾的處理-建立物件 System.IO名稱空間的資料夾操作類別分為Directory類別方法和DirectoryInfo類別的實例方法兩種。在本節主要說明DirectoryInfo類別的實例方法與屬性來處理資料夾,如下所示: Dim dirInfo As DirectoryInfo = New DirectoryInfo(path) 程式碼使用建構子建立DirectoryInfo物件,其參數是實際路徑,然後可以使用相關方法與屬性來處理資料夾。
7-2-3 資料夾的處理-DirectoryInfo物件方法與屬性
7-2-4 顯示檔案清單和資訊-顯示資料夾的檔案清單 在建立DirectoryInfo物件後,就可以使用GetFiles()方法取得其下的檔案清單陣列,如下所示: Dim subFiles() As FileInfo = dInfo.GetFiles() 程式碼取得FileInfo檔案物件陣列subFiles後,可以使用For Each迴路取得其中的FileInfo檔案物件,如下所示: Dim subFile As FileInfo For Each subFile In subFiles s &= "<tr><td>" & subFile.Name & "</td>" Next
7-2-4 顯示檔案清單和資訊-FileInfo類別的屬性1 Dim fInfo As FileInfo = New FileInfo(path) 程式碼使用New關鍵字的建構子來建立物件,參數是檔案的實際路徑。
7-2-4 顯示檔案清單和資訊-FileInfo類別的屬性2 在建立好物件後,即可使用相關屬性來取得檔案資訊,如下表所示:
7-2-5 檔案處理-建立物件 Web伺服器的檔案處理是指刪除、複製、移動伺服器的檔案和檢查檔案是否存在等操作。 在System.IO名稱空間類別的檔案操作方法和資料夾相似,分為File類別的類別方法和FileInfo類別的實例方法,本節主要說明FileInfo類別的實例方法,如下所示: Dim fileInfo As FileInfo = New FileInfo(path) 上述程式碼的參數path是檔案的實際路徑,在建立好FileInfo物件後,就可以使用相關方法執行檔案操作。
7-2-5 檔案處理-FileInfo物件方法與屬性
7-3 文字檔案讀寫、搜尋和取代 7-3-1 文字檔案讀寫的基礎 7-3-2 文字檔案的讀寫函數 7-3-3 文字檔案的搜尋和取代 7-3-4 文字檔案內容的編碼
7-3-1 文字檔案讀寫的基礎-說明 串流(Stream)觀念最早是使用在Unix作業系統,串流模型如同水管的水流一般,當程式開啟一個來源的輸入串流(例如:檔案、記憶體和緩衝區等),ASP.NET程式可以從輸入串流依序讀取資料,如下圖所示:
7-3-1 文字檔案讀寫的基礎- 步驟一:開啟或建立文字檔案的串流物件 首先使用FileInfo類別的CreateText()方法建立全新的文字檔案,如下所示: Dim sw As StreamWriter = fileInfo.CreateText() 對於存在的文字檔案,我們可以使用StreamReader類別開啟讀取檔案,如下所示: Dim sr As StreamReader = _ New StreamReader(path) 如果開啟檔案是用來寫入資料,就是使用StreamWrite類別,如下所示: Dim sw As StreamWriter = _ New StreamWriter(path)
7-3-1 文字檔案讀寫的基礎- 步驟二:執行檔案串流內容的讀寫 在建立StreamReader和StreamWriter串流物件後,就可以使用相關方法來執行讀寫。StreamWriter類別的相關方法,如下表所示: StreamReader類別的相關方法,如下表所示:
7-3-1 文字檔案讀寫的基礎- 步驟三:關閉檔案串流 在處理完文字檔案的讀寫後,就可以將緩衝區資料寫入和關閉檔案串流,如下所示: sw.Flush() sw.Close() Close()方法可以關閉StreamWriter或StreamReader串流物件,Flush()方法是StreamWriter類別繼承自TextWriter類別的方法,可以清除緩衝區資料,強迫將緩衝區資料寫入檔案。
7-3-2 文字檔案的讀寫函數- 程序createTextFile() 程序createTextFile()是使用FileInfo物件的CreateText()方法來建立文字檔案,如下所示: Sub createTextFile(file As String) Dim path As String = Server.Mappath(file) Dim fileInfo As FileInfo = New FileInfo(path) If fileInfo.Exists = False Then Dim sw As StreamWriter = _ fileInfo.CreateText() sw.Close() End If End Sub
7-3-2 文字檔案的讀寫函數- 函數readTextFile() Function readTextFile(file As String) As String Dim path As String = Server.Mappath(file) Dim sr As StreamReader = New StreamReader(path) Dim fileContent As String = sr.ReadToEnd() sr.Close() Return fileContent End Function
7-3-2 文字檔案的讀寫函數- 程序saveTextFile() Sub saveTextFile(file As String, textLine As String) Dim path As String = Server.Mappath(file) Dim sw As StreamWriter = _ New StreamWriter(path) sw.WriteLine(textLine) sw.Flush() sw.Close() End Sub
7-3-2 文字檔案的讀寫函數- 程序appendTextFile() 程序saveTextFile()改為FileInfo物件的AppendText()方法來開啟StreamWriter寫入串流,寫入字串是新增在檔尾,並不會覆寫原來內容,如下所示: Sub appendTextFile(file As String, appendLine As String) Dim path As String = Server.Mappath(file) Dim fileInfo As FileInfo = New FileInfo(path) Dim sw As StreamWriter = _ fileInfo.AppendText() sw.WriteLine(appendLine) sw.Flush() sw.Close() End Sub
7-3-3 文字檔案的搜尋和取代- 函數searchTextFile() 函數searchTextFile()可以在檔案搜尋指定字串,傳入參數依序為搜尋文字檔案和關鍵字,傳回值True表示找到,如下所示: Function searchTextFile(file, searchText) As Boolean Dim isFound As Boolean = False Dim path As String = Server.Mappath(file) Dim sr As StreamReader = New StreamReader(path) Dim fileContent As String = sr.ReadToEnd() If fileContent.IndexOf(searchText) >= 0 Then isFound = True End If sr.Close() Return isFound End Function
7-3-3 文字檔案的搜尋和取代- 函數replaceTextFile()1 Function replaceTextFile(file,target,repStr) As Integer Dim fileContent As String = "" Dim textLine, strLeft, strRight As String Dim pos, begin, count As Integer Dim path As String = Server.Mappath(file) Dim sr As StreamReader = New StreamReader(path) count = 0 Do textLine = sr.ReadLine() pos = 0
7-3-3 文字檔案的搜尋和取代- 函數replaceTextFile()2 Do begin = pos pos = textLine.IndexOf(target, begin) If pos >= 0 Then If pos = 0 Then strLeft = "" Else strLeft = textLine.Substring(begin, pos) End If strRight=textLine.Substring( _ pos+target.Length) textLine = strLeft & repStr & strRight count = count + 1
7-3-3 文字檔案的搜尋和取代- 函數replaceTextFile()3 fileContent = fileContent & textLine & _ Convert.ToChar(13) & _ Convert.ToChar(10) End If Loop While pos >= 0 Loop Until sr.Peek() = -1 sr.Close() Dim sw As StreamWriter = New StreamWriter(path) sw.WriteLine(fileContent) sw.Flush() sw.Close() Return isFound End Function
7-3-4 文字檔案內容的編碼-寫入 一般來說,文字檔案內容都是使用系統預設的ANSI編碼(即使用Encoding.Default),如果文字檔案內容不是使用系統的標準編碼,我們可以在開啟StreamWriter串流物件時,指定檔案編碼,如下所示: Dim sw As StreamWriter = New StreamWriter( _ path, True, Encoding.UTF7) 程式碼在開啟StreamWriter串流時指定編碼,第2個參數True表示開啟檔案是新增至檔尾,如為False表示覆寫存在內容,最後一個參數是編碼,以此例為UTF-7。
7-3-4 文字檔案內容的編碼-讀取 如果檔案內容不是標準編碼,我們在開啟StreamReader串流物件讀取檔案時,也需要指定編碼,才能正確讀取檔案內容,如下所示: Dim sr As StreamReader = _ New StreamReader( _ path, Encoding.UTF7) 程式碼的第2個參數是使用的編碼。
7-4 二進位檔案的處理-開啟 System.IO名稱空間的類別可以將檔案內容開啟成為串流,除了文字檔案外,一樣可以處理二進位檔案。以網頁來說,二進位檔案主要是指圖片檔案,換句話說,我們可以建立FileStream類別的串流物件來開啟圖片檔案,如下所示: Dim objStream As FileStream objStream = File.Open(path, FileMode.Open) 程式碼使用File類別Open()方法開啟FileStream串流。另一種方法是使用建構子,如下所示: objStream = New FileStream(path, _ FileMode.Open)
7-4 二進位檔案的處理-讀取 在開啟二進位檔案的FileStream串流後,因為內容是二進位資料,所以需要建立Byte資料型態陣列的緩衝區來存放,如下所示: Dim imageBuffer(objStream.Length) As Byte 程式碼宣告長度為檔案串流尺寸的緩衝區,接下來,就可以使用Read()方法讀取檔案內容,如下所示: objStream.Read(imageBuffer, 0, _ objStream.Length)
7-5 XML文件的處理 7-5-1 .NET Framework與XML 7-5-2 ASP.NET載入與瀏覽XML文件 7-5-3 ASP.NET與XSLT 7-5-4 ASP.NET與XPath
7-5-1 .NET Framework與XML-名稱空間 System.Xml:提供基本XML功能的類別和方法,包含DOM和XMLReader(即微軟版的SAX)的相關類別與方法。 System.Xml.Xsl:提供XSLT轉換XML文件的相關類別與方法。 System.Xml.XPath:提供XPath相關的類別與方法。 System.Xml.Schema:提供XML Schema驗證的相關類別與方法。
7-5-1 .NET Framework與XML-匯入名稱空間 在ASP.NET程式使用.NET Framework的XML時,需要匯入上述名稱空間,例如:匯入System.Xml名稱空間,如下所示: <%@ Import Namespace="System.Xml" %>
7-5-1 .NET Framework與XML- DOM節點類別 .NET Framwork的DOM支援Level 1和Level 2核心模組,主要的DOM節點類別,如下表所示:
7-5-2 ASP.NET載入與瀏覽XML文件-載入XML文件 ASP.NET程式是使用XmlDocument物件來載入 XML 文件,如下所示: Dim xmlDom As XmlDocument xmlDom = New XmlDocument() xmlDom.Load( _ Server.MapPath("Ch7-5.xml")) 程式碼在建立XmlDocument物件後,使用Load()方法來載入XML文件。
7-5-2 ASP.NET載入與瀏覽XML文件-瀏覽XML文件1 當ASP.NET程式載入XML文件建立XmlDocument物件後,就可以使用documentElement屬性取得根節點物件,如下所示: Dim node, nd As XmlNode node = xmlDom.DocumentElement book = node.FirstChild 程式碼使用FirstChild屬性取得第1個book子元素。
7-5-2 ASP.NET載入與瀏覽XML文件-瀏覽XML文件2 同樣的,我們可以使用HasChildNodes屬性檢查是否有子節點,ChildNodes屬性取得所有子節點的子樹,如下所示: For Each nd In book.ChildNodes Response.Write("<tr><td>" & _ nd.Name & "</td>") Response.Write("<td>" & _ nd.InnerText & "</td></tr>") Next 屬性清單的處理是使用XmlNamedNodeMap物件,如下所示: Dim atts As XmlNamedNodeMap atts = book.Attributes
7-5-2 ASP.NET載入與瀏覽XML文件-XmlDocument物件的屬性
7-5-3 ASP.NET與XSLT-Xml伺服端控制項 在伺服端可以使用XML文件配合XSLT文件,將XML文件輸出成HTML文件。 ASP.NET提供Xml伺服端控制項來顯示XML文件,或是XML與XSLT文件的轉換結果,如下所示: <asp:Xml Id="myxml" Runat="server"/> 標籤是名為myxml的Xml伺服端控制項,其相關屬性可以指定使用的XML或XSLT文件。
7-5-3 ASP.NET與XSLT-Xml伺服端控制項屬性 Xml伺服端控制項相關屬性可以指定使用的XML或XSLT文件,如下表所示:
7-5-3 ASP.NET與XSLT-執行XSLT轉換1 在ASP.NET程式匯入System.Xml和System.Xml.Xsl名稱空間後,就可以建立XmlDocument和XslTransform物件,然後配合Xml控制項來顯示轉換結果。 首先建立XmlDocument物件來載入XML文件,如下所示: Dim doc As XmlDocument = New XmlDocument() doc.Load(Server.MapPath("Ch7-5.xml")) 接著載入XSLT文件建立XslTransform物件,如下所示: Dim trans As XslTransform = new XslTransform() trans.Load(Server.MapPath("Ch7-5.xslt"))
7-5-3 ASP.NET與XSLT-執行XSLT轉換2 最後我們可以指定XML控制項的Document和Transform屬性,如下所示: myxml.Document = doc myxml.Transform = trans 程式碼指定相關屬性為XmlDocument和XslTransform物件,就可以在控制項執行XSLT轉換輸出成HTML文件。
7-5-4 ASP.NET與XPath1 XPath(XML Path Language)語言屬於第四代程式語言,這是一種宣告語言來在XML文件中走訪和標示節點位置,我們可以使用XPath語言來描述指定XML元素或屬性的位置,如同Windows作業系統硬碟資料夾的檔案路徑,如下所示: node = xmlDom.SelectSingleNode( _ "/library/book[2]/title") 上述程式碼的SelectSingleNode()方法參數就是XPath路徑字串,可以找到第2本圖書的title元素。
7-5-4 ASP.NET與XPath2 SelectNodes()可以取得XmlNodeList的節點集合,如下所示: nodes = xmlDom.SelectNodes( _ "/library/book[@sales='N']") For Each node In nodes Response.Write(node.Name & " - ") Response.Write(node.InnerText & "<br>") Next