奇妙的文件系統對象組件
作者 Chris Payne 翻譯 討飯貓
很久以前(其實就幾個月)就知道 Chinaasp 有個實際效果象黑客的ASE程序,最近 Chinaasp 又提供了精華區全文檢索功能。看來文件系統對象組件還是很有用的,對吧?如果你對此有興趣,可以看看這篇文章。本文屬入門級,修行還靠你自己,呵呵。
注意:我們在下文中要操作的是Web服務器的文件系統,所以首先要確定你對該服務器有足夠的權限。如果你不想麻煩你的Web Master,你也可以用微軟的Personal Web Server來進行你的試驗。
FSO對象包括 驅動器對象(Drive Object)用來存取本地盤或網絡盤, 文件系統對象(FielSystemObject 簡稱FSO)是用來存取文件系統 文件夾對象(Folder Object)用于存取文件夾的各種屬性 文本流對象(TextStream Object 簡稱TS)存取文件內容
使用以上對象,你的確可以在一臺電腦上為所欲為,但同樣也可能會造成災難,所以在使用FSO的時候要注意安全,特別是在Web應用中,Web服務器中會存儲諸如用戶信息,日志文件等等重要信息,更要格外小心。在本文中,我們主要探討FSO對象和TextStream對象
(FSO由Microsoft提供,所以本文內容只適用于Windows操作系統下的ASP編程。)
如何使用FSO?
要開始干壞事之前,首先要學會建立FSO。如果你曾經在ASP中創建過對象,那么這事好辦:
<% Set fso = Server.CreateObject("Scripting.FileSystemObject") %>
現在我們已經建立了FSO,并賦值給變量fso,接下來就可以使用我們熟悉的object.method方法來使用它了(如果你對對象的操作不熟悉,請自己去補課,這里恕不奉陪)。在下面的例子中,主要使用的是fso.method和fso.property。
(FSO模塊來自微軟提供的腳本運行庫scrrun.dll中,許多應用系統都會調用它,例如Access,Word等等,并非專為ASP應用開發。)
下面是我們要用到的部分FSO方法:
CopyFile 拷貝一個或多個文件 CreateTextFile 創建一個文件并返回一個TS對象 DeleteFile 刪除一個文件 OpenTextFile 打開一個文件并返回一個可用于讀和添加的TS對象。
要獲得完整的FSO方法,請參看MSDN。下面看個例子吧。
寫文件
設想你要建立一個簡單的guestbook,而又不想用復雜的數據庫,或者你的ISP限制你用數據庫,大可以用FSO來干。 假設你要從用戶提交的form中收集信息,html這樣寫.
<html> <body> <form action="formhandler.asp" method="post"> <input type="text" size="10" name="username"> <input type="text" size="10" name="homepage"> <input type="text" size="10" name="Email"> </form> </body> </html>
再看看用于處理這個form的formhandler.asp。
<% ' 獲取 form信息 strName = Request.Form("username") strHomePage = Request.Form("homepage") strEmail = Request.Form("Email")
' 建立fso對象 Set fso = Server.CreateObject("Scripting.FileSystemObject")
path = "c:\temp\test.txt" ForReading = 1, ForWriting = 2, ForAppending = 3
' 打開文件 set file = fso.opentextfile(path, ForAppending, TRUE)
' 把信息寫入文件 file.write(strName) & vbcrlf file.write(strHomePage) & vbcrlf file.write(strEmail) & vbcrlf
' 關閉并清除對象 file.close set file = nothing set fso = nothing
看看上面,OpenTextFile方法返回了一個TS對象,TS對象提供了例如Write,ReadLine,SkipLine等一系列的方法來操作文件內容。VB常量vbcrlf是換行符。
(我們在OpentextFile方法中指定了TRUE參數,通知系統當文件不存在時生成一個新文件。如果不用TRUE,當文件不存在時就會返回一個難看的錯誤提示。)
現在打開c:\temp\test.txt,你可以看到如下信息:
User's name User's home page User's email
當然,實際內容是用戶的輸入。哈,一個簡單的guestbook誕生啦。
讀文件
好,現在我們的guestbook里已經存儲了不少用戶的信息了,如果這時一個用戶想看看我們訪客的信息,我們得把信息再還原出來。由于不是數據庫,得自己動手來解決分段問題。看看test.txt,每三行就是一個用戶的信息,好辦:
<% ' 建立fso對象 set fso = Server.Createobject("Scripting.FileSystemObject") path = "c:\temp\test.txt"
'打開文件 set file = fso.opentextfile(path, 1)<-- 用于讀
do until file.AtEndOfStream Response.write("Name: " & file.ReadLine & " ") Response.write("Home Page: " & file.ReadLine & " ") Response.write("Email: " & file.ReadLine & "<p>") loop
' 關閉并清除 file.close set file = nothing set fso = nothing %>
(這里我們只是將信息簡單輸出,你可以根據實際情況作調整,包括輸出到表格和DHTML form中。)
ReadLine方法用于從文件中讀取一行,下次調用ReadLine方法將讀取下一行。AtEndOfStream是TS對象的一個屬性,讓你知道是否到達文件結尾。
假設由于某種原因文件有問題,例如某個用戶只有兩行,那么我們會得到以下錯誤信息:
Server object error 'ASP 0177 : 800a003e'
所以加入一些錯誤處理代碼是必要的。
FSO的權限問題
現在我們已經對FSO有一些基本認識了,是時候來討論一下FSO的權限問題。FSO的讀取權限就是創建FSO的賬號所擁有的權限。如果某人從Internet上使用這個頁面,那么創建FSO的就是Internet賬號。如果你用administrator本機登錄并訪問頁面,那么建立的FSO就擁有administrator的權限。
Internet賬號(IUSER_機器名)通常只有讀權限,這意味著用戶永遠無法寫guestbook文件。所以必須想辦法解決。
第一個辦法,是讓用戶首先要用一個有寫權限的賬號登錄。但實際上所有從Internet訪問的用戶都是以anonymous登錄,所以這個方法比較難實現。
第二個方法是建立一個允許賬號為 IUSER_機器名 的用戶讀寫的目錄。但這樣可能會帶來安全漏洞。如果這個目錄讓黑客知道了,就可以往里面寫一些代碼并通過某種方式運行它,那你就慘了。所以最好將這個目錄建立在Web路徑之外(也就是inetpub路徑之外)。
用FSO實現search功能
現在讓我們來做更進一步的工作,用FSO在我們的Web站點上實現search功能。建立搜索引擎的關鍵是遞歸。
首先來建立搜索頁面。假設我們已經給用戶提供了一個輸入搜索字符串的頁面。
Dim objFolder Dim strSearchText Dim objFSO
strSearchText = Request.Form("SearchText")<-- 搜索字符串
' 建立 FSO 和文件夾對象 Set fso = Server.CreateObject("Scripting.FileSystemObject") Set objFolder = objFSO.GetFolder(Server.MapPath("/"))
Search objFolder
上面的代碼只是進行了一些變量初始化工作,真正的serach工作由下面這個Search函數執行。
Function Search(objFolder) Dim objSubFolder
'循環搜尋當前文件夾中的每個文件 For Each objFile in objFolder.Files
Set objTextStream = objFSO.OpenTextFile(objFile.Path,1) <-- For Reading
'把文件內容讀入一個變量 strFileContents = objTextStream.ReadAll
'如果在文件中找到該字符串,寫個指到該文件的鏈接 If InStr(1, strFileContents, strSearchText, 1) then Response.Write "<A HREF=""/" & objFile.Name &""">" & objFile.Name & "</A><BR>" bolFileFound = True End If
objTextStream.Close
Next
'以下是遞歸部分 ' 如果其中有子目錄,再調用Search函數 For Each objSubFolder in objFolder.SubFolders Search objSubFolder Next
End Function
該程序會自動搜索Web root目錄以下的所有子目錄,還不錯吧?
(FSO要使用物理絕對路徑,而不是Web Path的相對路徑。例如,要打開的是c:\inetpub\wwwroot\temp\index.html,而不能是www.enfused.com/temp/index.html 或 /temp/index.html。要將后一種路徑轉換為物理絕對路徑,使用Server.MapPath("filename")。)
隨著文件和子目錄數的增加,程序運行的時間會變長。所以如果是要提供繁重的搜尋功能,還是建議使用象 Microsoft Index Server這樣的專業工具。
用FSO進行目錄管理
現在知道FSO的好處了吧?下面我們嘗試用FSO來做更復雜一些的工作。
Web目錄管理就是在Web環境下進行文檔的新建刪除改名移動等工作,一個好的Web目錄管理工具可以為用戶提供一個與我們慣用的環境一樣的操作方法來管理Web服務器上的文件。
那么先讓我們來試試文件改名。首先要告訴大家,不幸得很,FSO不允許直接文件改名,所以我們要繞個彎進行。
<% ' 建立fso對象 set fso = Server.Createobject("Scripting.FileSystemObject")
path = "c:\temp\test.txt" strDate = Replace(Date(), "/", "") strDir = "c:\inetpub\wwwroot\articles\" & strDate
strNewFileName = Hour(Now) & "_" & Minute(Now) & "_" &second(Now) & ".html"
' 打開舊文件 set file = fso.opentextfile(path, 1)<-- 用于讀 strText = file.readall set file = nothing
' 檢查是是否要建立文件夾 if not fso.folderexists(Server.MapPath(strDir)) then set f = fso.CreateFolder(Server.MapPath(strDir)) else set f = fso.GetFolder(Server.MapPath(strDir)) end if
' 創建并寫入新文件 set file = fso.Createtextfile(f.path & "\" & strNewFileName) file.write(strText)
set f = nothing file.close set file = nothing
' 刪除舊文件 fso.DeleteFile(path & "\" & rst("FileName") & i)
' 清除 set fso = nothing %>
我們在這里特別舉這個例子就是因為FSO在這個功能上存在缺陷,所以我們必須分兩步走。首先新建一個文件,注意,由于用戶可能將文件改名到另一個目錄下,所以我們必須判斷新目錄是否存在(就是if not fso.folderexists那段代碼)。新文件建好后,用fso.DeleteFile 將舊文件刪除。
FSO功能上的弱點
FSO還是存在一些弱點。例如,它在處理二進制文件的時候就不那么方便。對于象MS Word文檔,圖像等許多文件,你只能執行移動,刪除等操作,而不能打開,讀/寫。當然,FSO提供了另外一套操作它們的方法(具體請參考MSDN),但始終不如我們慣用的open方法那么順手。
另一個不足與文件大小有關。由于FSO操作需要經常地將文件內容讀入內存,文件有多大,就需要多少內存,所以如果你要處理大文件或一大堆小文件的話,內存的開銷會很可觀,可能會對系統運行速度有影響。解決辦法是將大文件分段處理,并記住經常地清除內存(把變量設為null或"",set 對象=nothing)。
此外,FSO不能改變文件和文件夾的屬性。例如,在建立guestbook的例子中,其實有一個安全機制我們沒有實現,就是將保存信息的文件的屬性設為只讀,只有在更新的時候才臨時改為可寫,寫完后再改回只讀,許多用CGI或Perl寫的guestbook程序都有這種功能,可惜用FSO無法實現該功能。
FSO還能干些什么?
總的來說,FSO還是很強大的。FSO還有一些一般沒人注意到的很酷的功能。下面列出一些,當你看完可能會說“呀,我以前怎么不知道。”呵呵。
GetSpecialFolder 方法 返回一個特殊的Windows文件目錄:Windows安裝文件目錄,系統文件目錄,臨時文件目錄。使用方法分別是:FSO.GetSpecialFolder([0, 1, or 2])
GetTempName 方法 返回一個隨機生成的臨時文件或文件夾。象處理上面所說的將大文件分割處理的時候這個功能特別有用。(討飯貓:如果Win98常死機的話,我們經常可以在Windows根目錄下看到大量的長度為0的隨機文件名,估計就是這個用途)
GetAbsolutePathName 方法 返回一個文件夾的絕對路徑(有點象Server.MapPath)。例如,FSO.GetAbsolutePathName("region")會返回象"c:\mydocs\myfolder\region" 這樣的路徑,具體取決于你的當前目錄。
GetExtensionName 方法 返回文件的擴展名。例如 FSO.GetExtensionName("c:\docs\test.txt") 返回 "txt"。
GetBaseName 和 GetParentFolder 方法 分別返回根目錄名和父目錄名。例如 FSO.GetParentFolder ("c:\docs\mydocs") 返回 "docs"。
Drives 屬性 返回本機上所有驅動器的集合。如果你要建立一個explorer風格的界面,這個功能再有用不過。
記住要建立一套完善的錯誤信息處理機制,因為上面這些功能如果遇到象文件夾不存在之類錯誤時,會返回一些可惡的錯誤代碼。 看到這里,是不是覺得FSO有用呢?實際上,我們所提到的內容只是冰山的一角。在Enfused等大站點上,還可以看到更多與此有關話題的討論。
Copyright 1999-2000 internet.com Corp. All RIGHTS RESERVED.
|