procedure TForm1.Button1Click(Sender: TObject);
var
iFileHandle: Integer;
iFileLength: Integer;
iBytesRead: Integer;
Buffer: PChar;
i: Integer
begin
if OpenDialog1.Execute then
begin
try
iFileHandle := FileOpen(OpenDialog1.FileName, fmOpenRead);
iFileLength := FileSeek(iFileHandle,0,2);
FileSeek(iFileHandle,0,0);
Buffer := PChar(AllocMem(iFileLength + 1));
iBytesRead = FileRead(iFileHandle, Buffer, iFileLength);
FileClose(iFileHandle);
for i := 0 to iBytesRead-1 do
begin
StringGrid1.RowCount := StringGrid1.RowCount + 1;
StringGrid1.Cells[1,i+1] := Buffer[i];
StringGrid1.Cells[2,i+1] := IntToStr(Integer(Buffer[i]));
end;
finally
FreeMem(Buffer);
end;
end;
end;
Delphi同Object Pascal一樣支持三種文件類型,即:文本文件、記錄文件、無類型文件。
記錄文件在使用記事本等文件查看程序打開時,顯示為亂碼。文本文件則可以正常顯示,無類型文件基本不用。
6.1.1文本文件
文本文件類型的變量用如下方法聲明:
var
TextFileVar: Text ;
文本文件是以行為單位進行讀、寫操作的。由於每一行長度不一定相同,不能計算出給定行在文件中的確切位置,因而只能順序地讀寫。而且文本文件只能單獨為讀或寫而打開,在一個打開的文本文件上同時進行讀、寫操作是不允許的。
6.1.1.1文本文件的打開、關閉
文本文件的打開需要兩個步驟:(1). 文件變量與文件名關聯;(2). 初始化讀寫。
關聯文件變量與文件名調用AssignFile標准過程:
AssignFile ( TextFileVar , FileName ) ;
FileName 既可以是全路徑名,也可以僅是文件名。對於后者系統將在當前目錄下查找。
AssignFile是Delphi新提供的一個函數,其功能等價於Object Pascal中的Assign。而Assign在Delphi中更多地被用作一個方法名。
初始化讀寫有三種方式:
1. Reset : 為讀打開文件並把文件指針移動到文件首;
2. Rewrite : 為寫創建一個新文件;
3. Append : 為寫打開存在的文件並把文件指針定位在文件尾。
當使用Reset或Append過程而文件不存在時將會引發一個I/O異常。有關I/O異常的處理請參看本章例程和第十二章中的介紹。
文件的關閉很簡單,只須調用CloseFile過程即可。
雖然Delphi應用程序在退出時會自動關閉所有打開的文件,但自己動手關閉文件可以確保釋放文件句柄,並使程序的可移植性增強。
為保持兼容,Delphi也允許用戶用Assign建立關聯,Close關閉文件。
6.1.1.2文本文件的讀寫
從文本文件中讀取信息用Read、Readln兩個標准過程。
當讀入數值時,Read、Readln假定數值是用一個或多個空格分開的,而不是逗號、分號或其它字符。對如下一條語句:
Read ( TextFileVar , Num1 , Num2 , Num3 ) ;
如果文件中的數值是:
100200300
則能夠成功讀入,而若文件中的數值是
100200,300
則Read讀入“200,”並試圖把它轉化成一個數值時會引發一個異常。
當讀入字符是字符串時,Read、Readln過程總是讀取盡可能多的字符填充到字符串變量中或一直讀到行結束符為止。因此從文本文件中讀取格式化的字符串數據,必須聲明與其長度相匹配的字符串變量。如果要從文件中讀取單詞,必須先把文件中的每一行讀入字符串,然后再從字符串中逐個分析出單詞。或者一次只從文本文件中讀入一個字符並測試每個字符后是否是單詞斷開處。
格式化字符串之間的分隔符應讀入到一個臨時變量中,而字符串與數值、數值與數值間的分隔符讀入時會自動識別剔除。對如下一行數據:
Mon12:1040 50
定義
var
Day: string[3] ;
Time: string[5] ;
Num1, Num2: Integer ;
則須用如下的read 語句讀入:
read ( TextFileVar , Day , c , Time , Num1 , Num2 ) ;
C為一個臨時字符變量。
6.1.1.3文本文件的編輯
在Delphi中實現對一個文本文件的編輯,只須讓其與一個Tmemo控件建立關聯即可:
Memo1.Lines.LoadFromFile ( TextFileName ) ;
這樣在TMemo上所做的一切修改當調用Memo部件的SaveToFile方法后都會反映到文件中去。
6.1.2 記錄文件
記錄文件是一種操作更為靈活的文件類型。它允許同時為讀和寫打開,而且由於記錄文件中每條記錄的長度固定,所以可隨機存取。
記錄文件的類型變量可如下聲明:
var
RecordFileVar: file of RecordType;
RecordType是一個自定義的記錄類型。
有關記錄文件的操作我們將在下一節中結合例程進行討論。
6.1.3 無類型文件
無類型文件提供了底層的I/O通道,可用於存取可變長度記錄的文件。經常用於文件的復制操作中。由於Delphi提供了更好的方法(見第四節),所以無類型文件很少使用。有興趣的讀者可參看BlockRead、BlockWrite兩個聯機幫助主題。
6.1.4 Delphi的文件管理標准過程
根據功能我們把標准過程划分為十一類進行介紹。
6.1.4.1 文件的打開與關閉
AssignFile :把一個外部文件名和一個文件變量相關聯
Reset :打開一個存在的文件
Rewrite :創建並打開一個新文件(或覆蓋原有文件)
Append :以添加方式打開一個文件(只適用於文本文件)
CloseFile :關閉一個打開的文件
FileOpen :打開一個特定的文件並返回文件句柄
FileCreate :創建一個給定文件名的文件並返回文件句柄
FileClose :關閉一個特定句柄的文件
后邊三個文件主要供系統內部使用,在文件復制的編程中也往往會用到。它們操作的對象是文件句柄而不是文件變量。
6.1.4.2 文件定位
Seek:把文件當前位置移到指定部分
FilePos:返回文件的當前位置
Eoln:返回行結束標志
EOF:返回文件結束標志
FileSeek: 改變當前文件指針的位置
Seek與FileSeek的區別是:1. Seek僅用於記錄文件;2. FileSeek的參數是文件句柄、偏移量、起始位置。其中起始位置有文件首、當前位置、文件尾三種選擇。Seek的參數是文件變量、偏移量,偏移量是從文件首開始定位的。3. FileSeek的偏移量以字節數來計算,而Seek是根據記錄號進行移動。
Seek、FilePos僅用於記錄文件。但任何文件都可以看作是基於字節的記錄文件。下面一段程序表示了它們的用法。
{ 該例子的設計界面為一個包含TOpenDialog部件的窗體。}
uses Dialogs;
var
f: file of Byte;
size: Longint;
S: String;
y: Integer;
begin
if OpenDialog1.Execute then
begin
AssignFile(f, OpenDialog1.FileName);
Reset(f);
size := FileSize(f);
S := 'File size in bytes: ' + IntToStr(size);
y := 10;
Canvas.TextOut(5, y, S);
y := y + Canvas.TextHeight(S) + 5;
S := 'Seeking halfway into file...';
Canvas.TextOut(5, y, S);
y := y + Canvas.TextHeight(S) + 5;
Seek(f,size div 2);
S := 'Position is now ' + IntToStr(FilePos(f));
Canvas.TextOut(5, y, S);
CloseFile(f);
end;
end.
6.1.4.3 文件刪除與截斷
Erase:刪除一個存在的文件
DeleteFile:刪除一個文件
Truncate:從文件當前位置將文件截斷
Erase與DeleteFile的區別是:Erase以文件變量為參數,當文件不能刪除時引起一個異常;DeleteFile以文件名為參數,當文件不存在或不能刪除時返回False,而並不引起一個異常。
6.1.4.4 文件名操作
Rename:文件更名,以文件變量為操作對象
RenameFile:文件更名,參數為文件的原名和新名
ChangeFileExt :改變文件擴展名
ExpandFileName:返回文件全路徑名
ExtractFileExt :返回文件擴展名
ExtractFileName:從全路徑名中返回文件名
ExtractFilePath:返回特定文件的路徑
6.1.4.5 文件屬性
FileGetAttr:返回文件屬性
FileSetAttr:設置文件屬性
6.1.4.6 文件狀態
FileSize:返回文件對象大小
IOResult:返回上一次I/O操作的狀態
FileExists :檢測文件是否存在
6.1.4.7 文件日期
DateTimeToFileDate:把Delphi日期格式轉換為DOS日期格式
FileDateToDateTime:把DOS日期格式轉換為Delphi日期格式
FileGetDate:返回文件的DOS日期時間戳
FileSetDate:設置文件的DOS日期時間戳
6.1.4.8 文件讀寫
Read,Readln:從文本或記錄文件中讀取變量
Write:將指定變量寫入文本或記錄文件
Writeln:將指定變量寫入文本文件並寫入一個行結束標志
FileRead:從一個指定文件中讀取變量
FileWrite :向指定文件寫入數據
FileRead和FileWrite都是以文件句柄為操作對象,主要供系統內部使用。
6.1.4.9 目錄操作
MkDir:創建當前目錄的子目錄
ChDir:改變當前目錄
GetDir:返回特定磁盤的當前目錄
RmDir:刪除一個空子目錄
6.1.4.10 磁盤操作
DiskFree:返回磁盤自由空間
DiskSize:返回特定磁盤的大小
6.1.4.11 文件查找
FileSearch:查找目錄中是否存在某一特定文件
FindFirst :在目錄中查找與給定文件名(可以包含匹配符)及屬性集相匹配的第一個文件
FindNext:返回符合條件的下一個文件
FindClose :中止一個FindFirst / FindNext序列
有關文件管理標准過程/函數的更詳細資料,請查閱Delphi相關的Help主題。以上的大部分過程在后面都有應用實例,讀者可以從中體會其用法。
在Delphi的聯機幫助Help系統中把有關文件的過程/函數分為兩個主題:I/O Routine和File _Management Routine。前者大部分以文件變量為操作對象,而后者大部分以文件名或文件句柄為操作對象。這里為了方便讀者的使用,我們按功能重新進行了分類。在下一節中主要應用I/O Routine主題下的過程,而在第四節的綜合舉例中主要應用File_Management Routine主題下的過程。
另外,Windows提供了許多有關文件管理的API函數。雖然在一般情況下,利用Delphi提供的函數已足夠解決問題,但有時候仍然需要使用Windows API。在(6.4.4.2)中我們就用到了Windows API函數GetDriveType。有關Windows API函數的情況,請讀者參閱相關的資料,這里不再進行介紹。