文件處理之四文件系統

 

四、文件系統

在計算機科學技術中,常用“文件”這一術語來表示輸入輸出操作的對象。所謂“文件”,是指記錄在外部介質上的集合。例如用Word或Excel編輯製作的文檔或表格就是一個文件,把它存放在磁盤上就是一個磁盤文件,輸出到打印機上就是一個打印機文件。

文件通常存放在磁盤上,通過“路徑”指明它在磁盤上的位置。“路徑”是由目錄(也稱文件夾)和文件名組成。

1、文件說明與文件結構

文件是信息的集合,每個文件都有一個區別於其它文件的名字。下面先介紹如何對數據文件命名,然後再介紹VB中文件的一般結構和種類。

(1)文件說明

所謂文件說明,指的是文件的命名規則。在VB中,文件說明的一般格式爲:

    設備名:文件引用名

例如:A:myfile.abc

這裏的“A:”是設備名,而“myfile.abc”是文件引用名。

設備名是存放文件設備的名稱,如磁盤、磁帶、打印機等。在微機中,存放文件的主要設備是磁盤,其名稱通常爲A:,B:,C:,D:等,分別A,B,C,D驅動器。

文件引用名由兩部分組成,即文件基本名和擴展名。其中文件基本名以字母開頭(在DOS環境下,最多不超過8個字符,在Windows環境下,不超過255個字符);擴展名是可選的,最多不超過3個字符。

下面字符可以做文件基本名和擴展名:

  • 英文26個字母(大小寫均可);

  • 數字(0-9);

  • 特殊字符($ # & @ ! % () - _ ' ^ ~ / )。

完整的文件說明由設備名和文件引用名構成。對於磁盤文件,還可以含有路徑。例如:

    c:/textfile/sprot.tex 

另外,文件說明不區分大小寫。

(2)文件結構和分類

文件結構

爲了有效地存取數據,數據必須以某種特定的方式存放,這種特定的方式稱爲文件結構。

VB的文件由記錄組成,記錄由字段組成,字段又由字符組成。

字符:是構成文件的最基本單位。字符可以是數字、字母、特殊符號或單一字節。這裏說的字符一般爲西文字符,一個西文字符用一個字節存放。如果爲漢字字符包括漢字和全角字符,則通常由兩個字節存放。也就是說一個漢字字符相當於兩個西文字符。一般把用一個字節存放的西文字符稱爲“半角”字符,而把漢字和用兩個字符存放的字符稱爲“全角”字符。但VB支持雙字節字符,在計算字符串長度時,一個西文字符和一個漢字都作爲一個字符計算,只是它們所佔的內存空間不一樣。例如“VB程序設計”的長度爲6,而所佔的字節數爲10。

字段:也稱域。字段由若干個字符組成,用來表示一項數據。例如郵政編碼“100859”就是由6個字符組成的一個字段。而姓名“張三”也是一個字段,由2個漢字組成。

記錄:由一組相關的字段組成。例如在通信錄中,每個人的姓名、單位、地址、電話號碼、郵政編碼等構成一個記錄。在VB中,以記錄爲單位處理數據。

文件:文件由記錄構成,一個文件含有一個以上記錄。

文件分類

在計算機中,文件隨着分類標準的不同可分爲不同的類型。

按照文件的存取方式及其組成結構來分可以分爲兩種類型:順序文件、隨機文件;

順序文件:結構較簡單,文件中的記錄一個接一個地存放。在這種文件中,只知道第一個記錄的存放位置,其它記錄的位置無從知道。當要查找某個數據時,只能從文件頭開始,一個記錄一個記錄地順序讀取,直到找到爲止。這種類型的文件組織比較簡單,佔空間少,容易使用,但維護困難,適用於有一定規律且不經常修改的數據。

隨機文件:又稱直接存取文件,簡稱隨機文件或直接文件。隨機文件的每個記錄都有一個記錄號,在寫入數據時只要指定記錄號,就可以把數據直接存入指定位置。而在讀取數據時,只要給出記錄號,就可直接讀取。在記錄文件中,可以同時進行讀、寫操作,所以能快速地查找和修改每個記錄,不必爲修改某個記錄而像順序文件那樣,對整個文件進行讀、寫操作。其優點是數據存取較爲靈活、方便,速度快,容易修改,主要缺點是佔空間較大,數據組織複雜。

按照文件的數據編碼方式來分可以分爲ASCII碼文件和二進制文件;

ASCII碼文件:又稱文本文件。它以ASCII方式保存文件,可用字處理軟件建立和修改(必須以純文本文件保存)。

二進制文件:不能用普通的字處理軟件編輯,佔空間較小。

按照文件的特徵屬性來分可以分爲系統文件、隱藏文件、只讀文件、普通文件和存檔文件;

按照文件的數據性質來分可以分爲程序文件和數據文件。

程序文件:這種文件存放的是可以由計算機執行的程序,包括源文件和可執行文件。在VB中,擴展名爲.exe,.frm,.vbp,.vbg,.bas,.cls等的文件都是程序文件。

數據文件:數據文件用來存放普通的數據,例如學生的考試成績、職工工資、商品庫存等。這類數據必須通過程序來存取和管理。

2、文件的打開與關閉

在VB中,數據文件的操作按下述步驟進行:

打開(或建立)文件

一個文件必須先打開或建立後才能使用。如果一個文件已存在,則打開該文件;如果不存在,則建立該文件。

進行讀、寫操作

在打開(或建立)的文件上執行所要求的輸入輸出操作。在文件處理中,把內存中的數據傳輸到相關聯的外部設備(如磁盤)並作爲文件存放的操作叫做寫數據,而把數據文件中的數據傳輸到內存程序中的操作叫做讀數據。一般來說,在主存與外設的數據傳輸中,由主存到外設叫做輸出或寫;而由外設到主存叫做輸入或讀。

關閉文件

文件處理一般需要以上三步。在VB中,數據文件的操作通過有關的語句和函數來實現。

下表列出了三種直接文件訪問類型的各種文件訪問的所有語句和函數。

語句與功能

順序型

隨機型

二進制型

Open

X

X

X

Get

 

X

X

Input()

X

 

X

Input#

X

 

 

Line Input#

X

 

 

Print #

X

 

 

Put

 

X

X

Type..End Type

 

X

 

Write #

X

 

 

Close

X

 

X

順序的訪問是爲普通的文本文件的使用而設計的。文件中每一個字符都被假設爲代表一個文本字符或者文本格式序列,比如換行符(NL)。數據被存儲爲ASCII字符

而爲隨機型訪問打開的文件則認爲是由相同長度的記錄集合組成。可用記錄類型來創建由各種各樣的字段組成的記錄,每個字段可以有不同的數據類型。

數據作爲二進制信息存儲

 

二進制訪問允許使用文件來存儲所希望的數據。除了沒有數據類型或者記錄長度的含義外,它與隨機訪問很相似。

3、順序文件

所謂的順序文件,通常指的是普通的文本文件,文件中的字符包括文本字符及控制字符如",","chr(14)","cr,lf" ,"chr(10)等。

由於這類型文件的信息是按照順序從頭到尾按順序排列,而且只提供第一條記錄的存儲位置,所以對其中的數據信息進行處理是相當困難的。

(1)順序文件的打開

VB中用Open語句打開或建立一個文件。

打開順序文件的語法結構如下:

Open 文件說明 [For 方式] [Access 存取類型] [lock] As [#] 文件號 [Len=記錄長度]

Open語句的功能是:爲文件的輸入輸出分配緩衝區,並確定緩衝區所使用的存取方式。

Open語句的語法參數及其說明

格式中的Open、For、Access、As及Len爲關鍵字。

文件說明(Pathname):如前面所述指定了文件路徑和文件名。

方式(Mode):指定文件輸入、輸出方式。有Append,Binary,Input,Output或Random方式。

方式是可選的,如果省略,則爲隨機存取方式,即Random方式。

  • Output:指定順序輸出方式。
  • Input:指定順序輸入方式。
  • Append:指定順序輸出方式,與Output不同的是當用Append方式打開文件時,文件指針被定位在文件末尾。如果對文件執行寫操作,則寫入的數據附加到原來文件的後面。
  • Random:指定隨機存取方式,這是默然方式。在這種方式中,如果沒有Access子句,則在執行Open語句時,VB按下列順序打開文件:讀/寫、只讀、只寫。
  • Binary:指定二進制方式文件。在這種方式中,如果沒有Access子句,則打開文件的類型與Random方式相同。

存取類型(Access):用來指定訪問文件的類型,有Read、Write或ReadWrite操作。

  • Read:打開只讀文件。
  • Write:打開只寫文件。
  • ReadWrite:打開讀/寫文件。這種文件只對隨機文件、二進制文件及Append方式打開的文件有效。

鎖定(Lock):該子句只在多用戶或多進程環境中使用,用來限制其他用戶或其他進程對打開的文件進行讀寫操作。有Lock Shared、Lock Read、Lock Write和Lock Read Write操作。

  • 默認:如不指定鎖定類型,則本進程可以多次打開文件進行讀寫;在文件打開期間,其他進程不能對該文件執行讀寫操作。
  • Lock Shared:任何機器上的任何進程都可以對該文件進行讀寫操作。
  • Lock Read:不允許其他進程讀該文件。只在沒有其他Read存取類型的進程訪問該文件時,才允許這種鎖定。
  • Lock Write:不允許其他進程寫該文件。只在沒有其他Write存取類型的進程訪問該文件時,才允許這種鎖定。
  • Lock Read Write:不允許其他進程讀寫該文件。

如果不使用Lock子句,則默認爲Lock Read Write。

文件號(Filenumber):是一個整形表達式,其值在1到511之間。執行Open語句時,打開文件的文件號與一個具體的文件相關聯,其他輸入輸出語句或函數通過文件號與文件發生聯繫。

記錄長度(Reclength):是一個整形表達式,是小於或等於32767(字節)的一個數。當選擇該參量時,爲隨機存取文件設置記錄長度。對於用隨機訪問方式打開的文件,該值就是記錄長度,對於順序文件,該值就是緩衝字符數,對於二進制文件,將忽略Len子句。

在順序文件中,“記錄長度”不需要與各個記錄的大小相對應,因爲順序文件各個記錄的長度可以不相同。當打開順序文件時,在把記錄寫入磁盤或從磁盤讀出記錄之前,“記錄長度”指出要裝入緩衝區的字符數,即確定緩衝區的大小。緩衝區越大,佔用空間越大,文件的輸入輸出操作越快。默認時緩衝區的容量爲512字節。

特別說明:

  • 爲了滿足不同的存取方式的需要,對同一個文件可以用幾個不同的文件號打開,每個文件號有自己的一個緩衝區。對於不同的訪問方式,可以使用不同的緩衝區。但是,當使用Output或Append方式時,必須先將文件關閉,才能重新打開文件。而當使用Input、Random或Binary方式時,不必關閉文件就可以用不同的文件號打開文件。
  • Open語句兼有打開建立文件兩種功能。在對一個數據文件進行讀、寫、修改或增加數據之前,必須先用Open語句打開或建立該文件。如果爲輸入(Input)打開的文件不存在,則產生“文件未找到”錯誤;如果爲輸出(Output)、附加(Append)或隨機(Random)訪問方式打開的文件不存在,則建立相應的文件。此外,在Open語句中,任何一個參數的值如果超出給定的範圍,則產生“非法功能調用”的錯誤,而且文件不能被打開。

 下面的示例就是利用Open語句中參數的不同設置來做到文件的輸出與輸入。

  • 下列代碼以順序輸入模式打開C:/windows/win.ini文件

    Open "C:/windows/win.ini" For Input As #1 '打開已存在的數據文件,以便從文件中讀出記錄。

    close#1

  • 下列代碼只允許寫操作的二進制方式打開C:/windows/win.ini文件

    Open "C:/windows/win.ini" For Binary Access Write As #1 '以二進制方式打開只寫文件。

    close#1

  • 下列代碼以順序輸出方式打開C:/windows/win.ini文件

    Open "C:/windows/win.ini" For Output Lock Shared As #1 '如果文件存在,則打開該文件(如果不存在,則建立該文件),使記錄可以寫到該文件中,新寫入的記錄將覆蓋原來的記錄。

    close#1

  • 下列代碼只允許讀的二進制方式打開C:/windows/win.ini文件

    Open "C:/windows/win.ini" For Binary Access Read Lock Read As #1 '若要以其他方式打開文件,必須先關閉此文件

    close#1

  • 下列代碼只允許讀寫的二進制方式打開C:/windows/win.ini文件

    Open "C:/windows/win.ini" For Binary Access Read Write Lock Read Write As #1 '若要以其他方式打開文件,必須先關閉此文件

    close#1

(2)順序文件的文件的關閉

文件的讀寫操作結束後,應將文件關閉,這可以通過Close語句實現。其格式爲:

    Close[[#]文件號][,[#]文件號]……

說明: 

Close語句用來關閉文件,它是在打開文件之後進行的操作。格式中的“文件號”是Open語句中使用的文件號。關閉一個數據文件具有兩方面的作用,第一,把文件緩衝區中的所有數據寫到文件中;第二,釋放與該文件相關聯的文件號,以供其它Open語句使用。

Close語句中的“文件號”是可選的。如果指定了文件號,則把指定的文件關閉;如果不指定文件號,則把所有打開的文件全部關閉。

除了用Close語句關閉文件外,在程序結束時將自動關閉所有打開的數據文件。

Close語句使VB結束對文件的使用。它的操作十分簡單,但絕不是可有可無的,這是因爲磁盤文件同內存之間的信息交換是通過緩衝區進行的。如果關閉的是爲順序輸出而打開的文件,則緩衝區中最後的內容將被寫入文件中。當打開的文件或設備正在輸出時,執行Close語句後,不會使輸出信息的操作中斷。如果不使用Close語句關閉文件,則可能使某些需要寫入的數據不能從內存(緩衝區)送入文件中。

(3)順序文件的寫操作

前面講過,數據文件的寫操作分三步進行,即打開文件、寫入文件和關閉文件。其中打開文件和關閉文件分別由Open和Close語句來實現,寫入文件由Print #或Write #語句來完成

Print #語句

Print #的功能是:把數據寫入文件中。它與Print方法的功能類似,只不過Print方法所“寫”的對象是窗體、打印機或圖片框,而Print #語句所“寫”的對象是文件。

Print #語句格式:

Print # 文件號,[[Spc(n)│Tab(n)][表達式表][;│,]]

 例如:Print # 1,A,B,C

把變量A,B,C的值寫到文件號爲1的文件中。

    如果是Print A,B,C

把變量A,B,C的值“寫”到窗體上。

說明:

1)“文件號”的含義同前,數據被寫入該文件號所代表的文件中。

2)其它參量,包括Spc函數、Tab函數、“表達式表”及尾部的分號、逗號等與Print方法中相同。如“表達式表”也可以省略,如果省略,將向文件中寫入一個空行。分號和逗號分別對應緊湊格式和標準格式。但值得說明的是,在使用分號時,如果數據是數值,由於數值數據前有符號位,後有空格,所以使用分號不會給以後讀取數據造成麻煩,但是如果數據是字符串,特別是變長字符串,用分號分隔就有可能引起麻煩,因爲輸出的字符串數據之間沒有空格。例如,設:

    A="Beijing",B="Shanghai",C="Tianjin"

則執行:

    Print # 1,A;B;C

後,寫到磁盤上的信息爲“BeijingShanghaiTianjin”。爲了使輸出的各字符串明顯的分開,可以人爲的插入逗號,即改爲:

    Print # 1,A;",";B;",";C

這樣寫入文件的信息爲:“Beijing,Shanghai,Tianjin”。

3)實際上,Print #語句的任務只是將數據送到緩衝區,而數據由緩衝區寫到磁盤文件的操作是由文件系統來完成的。對於用戶來說,可以理解爲由Print #語句直接將數據寫入磁盤文件。但是執行Print #語句後,並不是立即把緩衝區中的內容寫入磁盤,只有滿足下列條件之一時才寫盤:

  • 關閉文件(Close)。

  • 緩衝區已滿。

  • 緩衝區未滿,但執行下一個Print #語句。

例1:

Private Sub Form_Click()
    Open "c:/temp/tel.dat" For Output As #1
    Tpname = InputBox("請輸入姓名:", "數據輸入")
    Tptel = InputBox("請輸入電話號碼:", "數據輸入")
    TpAddr = InputBox("請輸入地址:", "數據輸入")
    Print #1, Tpname, Tptel, TpAddr
    Close #1
End Sub

這個過程的執行是:先在C盤的temp目錄下打開一個名爲tel.dat的輸出文件(如果沒有該文件,則建立一個),文件號爲1,然後分別輸入姓名、電話號碼、地址,最後關閉。

注意:這裏的“temp”文件夾要存在,如果沒有,可以先在C盤下建立,當然,也可以用其它名字。可用“記事本”查看。

Write #語句

格式:

    Write # 文件號,[表達式表]

功能:

Print #語句一樣,用Write #可以把數據寫入順序文件中。例如:

    Write # 1,A,B,

將把變量A,B,C的值寫入文件號爲1的文件中。

說明:

1)“文件號”和“表達式表”的含義同前。當使用Write #語句時,文件必須以Output或Append方式打開。“表達式表”中的各項以逗號分開。

2)Write # 語句與Print #語句的功能基本相同,其主要區別有以下兩點:

  • 當用Write # 語句向文件寫數據時,數據在磁盤上以緊湊格式存放,能自動地在數據項之間插入逗號,並給字符串加上雙引號。一旦最後一項被寫入,就插入新的一行。 
  • Write # 語句寫入的正數的前面沒有空格。

例2:

Private Sub Form_Click()
    Open "c:/Temp/tel1.dat" For Output As #1
    unit = InputBox("Enter unit:")
    While UCase(unit) <> "DONE" '當輸入done時退出循環。
    tel = InputBox("Telephone number:")
    Write #1, unit, tel
    Write #1, '寫入一空行。
    nowdate = #4/28/2004#
    Write #1, nowdate  '寫入日期。
    unit = InputBox("Enter unit:")
    Wend
    Close #1
    End
End Sub

可將該例與例1比較。

3)如果試圖用Write #語句把數據寫到一個用Lock語句限定的順序文件中去,則會發生錯誤。

用Open語句建立的順序文件是ASCII文件,可以用字處理程序來查看或修改。順序文件由記錄組成,每個記錄是一個單一的文本行,它以回車換行序列結束。每個記錄又被分成若干個字段,這些字段是記錄中按同一順序反覆出現的數據塊。在順序文件中,每個記錄可以具有不同的長度,不同記錄中的字段的長度也可以不一樣。

當把一個字段寫入變量時,存儲字段的變量的類型決定了該字段的開頭和結尾。如果把字段存入字符串變量,則下列符號標示該字符串的結尾:

  • 雙引號(""):當字符串以雙引號開頭時;
  • 逗號(,):當字符串不以雙引號開頭時;
  • 回車-換行:當字段位於記錄的結束處時。

如果把字段寫入數據變量,則下列符號標示該字段的結尾:

  • 逗號;
  • 一個或多個空格;
  • 回車-換行。

例3:從鍵盤上輸入4個學生的數據,然後把它們存放到磁盤文件中。

學生的數據包括姓名、學號、年齡、住址,用一個記錄類型來定義。按下述步驟編寫程序:

在標準模塊中定義如下記錄類型:

Type stu
    stname As String * 10
    num As Integer
    age As Integer

    addr As String * 20
End Type

 

在窗體層輸入如下代碼:

Option Base 1

編寫如下的窗體事件過程:

Private Sub Form_Click()
    Static stud() As stu
    Open "c:/Temp/stu_list" For Output As #1
    n = InputBox("Enter number of student:")
    ReDim stud(n) As stu
    For i = 1 To n
        stud(i).stname = InputBox("Enter stud " & i & " Name:")
        stud(i).num = Val(InputBox("Enter stud " & i & " Number:"))
        stud(i).age = Val(InputBox("Enter stud " & i & " Age:"))
        stud(i).addr = InputBox("Enter stud " & i & " Address:")
        Write #1, stud(i).stname, stud(i).num, stud(i).age, stud(i).addr
    Next i
    Close #1
    End
End Sub

程序運行後,從鍵盤上輸入學生人數如4個,分別輸入他們的姓名、學號、年齡、住址。

在字處理軟件中查看內容爲:

"王大力    ",9901,19,"3號樓202室          "
"張  紅    ",9902,20,"3號樓204室          "
"李  明    ",9903,21,"3號樓205室          "
"向  陽    ",9904,18,"3號樓208室          "

可以看出,由於用Write #語句執行寫操作,文件中各數據項用逗號分開,且字符串放在雙引號中。

(4)順序文件的讀操作

順序文件的讀操作分三步進行,即打開文件、讀數據文件和關閉文件。其中打開、關閉文件的操作如前所述,讀數據的操作由Input #語句和Line Input #實現

Input #語句

格式:

    Input # 文件號,變量表

功能:

Input #語句從一個順序文件中讀出數據項,並把這些數據項賦給程序變量。例如:

    Input #1,A,B,C

從文件中讀出3個數據項,分別把它們賦給A,B,C三個變量。

說明:

1)“文件號”的含義同前。“變量表”由一個或多個變量組成,這些變量既可以是數值變量,也可以是字符串變量或數組元素,從數據文件中讀出的數據賦給這些變量。文件中的數據項的類型應與Input #語句中變量的類型匹配。

2)在用Input #語句把讀出的數據賦給數值變量時,將忽略前導空格、回車或換行符,把遇到的第一個非空格、非回車和換行符作爲數值的開始,遇到空格、回車或換行符則認爲數值結束。對於字符串數據,同樣忽略開頭的空格、回車或換行符。如果需要把開頭帶有空格的字符串賦給變量,則必須把字符串放在雙引號中。

3)Input #與InputBox函數類似,但InputBox要求從鍵盤上輸入數據,而Input #語句要求從文件中輸入數據,而且執行Input #語句時不顯示對話框。

4)Input #也可用於隨機文件中。

例4:把前面建立的學生數據文件(stu_list)讀到內存,並在屏幕(窗體)上顯示出來。

該程序標準模塊不變,窗體層代碼也一樣,只是窗體事件過程爲:

Private Sub Form_Click()
    Static stud() As stu
    Open "c:/Temp/stu_list" For Input As #1
    n = InputBox("Enter number of student:")
    ReDim stud(n) As stu
    Print "姓  名"; Tab(20); "學  號"; Tab(30); "年齡"; Tab(40); "地址"
    Print
    For i = 1 To n
    Input #1, stud(i).stname, stud(i).num, stud(i).age, stud(i).addr
    Print stud(i).stname; Tab(20); stud(i).num; Tab(30); stud(i).age; Tab(40); stud(i).addr
    Next i
    Close #1
End Sub

運行結果爲:

例5:見教材P356。利用Print #語句從一個文件中讀取數據,然後把它顯示在窗體上。

Private Sub Form_Click()
    Dim Str1 As String
    Open "c:/windows/win.ini " For Input As #1
    Do While Not EOF(1)
    Input #1, Str1
    Form1.Print Str1
    Loop
    Close #1
End Sub

關於EOF函數:
功能:用來測試文件的結束狀態。
格式:EOF(文件號)
利用
EOF函數,可以避免在文件輸入時出現“輸入超出文件尾”的錯誤。即在文件輸入期間,可以用EOF測試是否到達文件尾。對於順序文件,如果已到文件末尾,則EOF函數返回True,否則返回false;對於隨機文件和二進制文件,如果最後執行的Get語句未能讀到一個完整的記錄,則返回True,這通常發生在試圖讀文件結尾以後的部分時。
EOF函數常用來在循環中測試是否已到文件尾,一般結構爲:
          Do While Not EOF(1)
               文件讀寫語句
          Loop

Line Input #語句

格式:

    Line Input # 文件號,字符串變量

功能:

Line Input #語句從一個順序文件中讀取一個完整的行,並把它賦給一個字符串變量。

說明:

1)“文件號”的含義同前。“字符串變量”是一個字符串簡單變量名,也可以是一個字符串數組元素名,用來接收從順序文件讀出的字符串。

2)在文件操作中,Line Input #是十分有用的語句,它可以讀取順序文件一行的全部內容,直至遇到回車符爲止。此外,對於以ASCII碼存放在磁盤上的各種語言源程序,都可以用Line Input #語句一行一行地讀取。

Line Input #與Input #語句功能類似,只是Input #語句讀取的是文件中的數據項,而Line Input #語句讀取的是文件中的一行。

3)Line Input #語句也可用於隨機文件。

Line Input #語句常用來複制文本文件,見下例:

例6:把一個磁盤文件的內容讀到內存並在文本框中顯示出來,然後把該文本框中的內容存入另一個磁盤文件。

首先用字處理軟件(例如“記事本”)建立一個名爲“Smtext1.txt”的文件(該文件存放在C盤的Temp目錄下),內容如下:

經五丈原
鐵馬雲雕共絕塵,柳營高壓漢宮春。
天清殺氣屯關右,夜半妖星照渭濱。
下國臥龍空寤主,中原得鹿不由人。
象牀寶帳無言語,從此譙周是老臣。

該文件有6行,輸入時,每行均以回車鍵結束。

在窗體上建立一個文本框,MultiLine屬性設置爲True,然後編寫如下代碼:

Private Sub Form_Click()
    Open "c:/Temp/smtext1.txt" For Input As #1
    Text1.FontSize = 12
    Text1.FontName = "黑體"
    Do While Not EOF(1)
        Line Input #1, aspect
        whole = whole + "" + aspect + Chr(13) + Chr(10)
    Loop
    Text1.Text = whole
    Close #1
    Open "c:/Temp/smtext2.txt" For Output As #1
    Print #1, Text1.Text
    Close #1
End Sub

程序說明:

上述過程首先打開一個磁盤文件smtext1.txt,用Line Input #語句把該文件的內容一行一行地讀到變量aspect中,每讀一行,就把該行連到變量whole,加上回車換行符。然後把變量whole的內容放到文本框中,並關閉該文件。,此時文本框將分行顯示smtext1.txt的內容。之後,程序建立一個名爲smtext2.txt的文件,並把文本框的內容寫入該文件。所以程序運行結束後,文本框及兩個磁盤文件具有相同的內容。

運行後的窗體界面爲:

Input函數

格式:

Input(n,#文件號)

功能:

Input函數返回從指定文件中讀出的n個字符的字符串。也就是說,它可以從數據文件中讀取指定數目的文件。例如:

    x=Input(100,#1)

從文件號爲1的文件中讀取100個字符,並把它賦給變量x。

Input函數執行所謂“二進制輸入”。它把一個文件作爲非格式的字符流來讀取。例如,它不把回車-換行序列看作是一次輸入操作的結束標誌。因此,當需要用程序從文件中讀取單個字符時,或者是用程序讀取一個二進制的或非ASCII碼文件時,使用Input函數較爲適宜。

例7:編寫程序,在文件中查找指定的字符串。

爲了查找文件中指定的字符串,可以先打開文件,用Input(1,1)搜索要查找的字符串的首字符,再試着進行完整的匹配。更直觀的做法是:把整個文件讀入內存,放到一個變量中,然後從這個變量中查找所需要的字符串。在VB中,一個字符串變量最多可存放20億個字符。

首先用字處理軟件(例如“記事本”)建立一個名爲“xyz.txt”的文件(該文件存放在C盤的Temp目錄下),作爲練習,可以隨便輸入。

然後在窗體中添加如下程序:

Private Sub Form_Click()
    Q = InputBox("請輸入要查找的字符串:")
    Open "c:/Temp/xyz.txt" For Input As #1
    X = Input(LOF(1), 1) '把整個文件內容讀入變量X中。
    Close #1
    y = InStr(1, X, Q)
    If y <> 0 Then
        Print "找到字符串"; Q
    Else
        Print "未找到字符串"; Q
    End If
End Sub

關於LOF函數:
功能:返回給文件分配的字節數(即文件的長度),與在DOS下用dir命令所顯示的數值相同。
格式:LOF(文件號)

2、隨機文件

隨機文件有以下特點:

1)隨機文件的記錄是定長記錄,只有給出記錄號n,才能通過[(n-1)×記錄長度]計算出該記錄與文件首記錄的相對地址。因此在用Open語句打開文件時,必須指定記錄的長度。

2)每個記錄劃分爲若干個字段,每個字段的長度等於相應的變量的長度。

3)各變量(數據項)要按一定格式置入相應的字段。

4)打開隨機文件後,既可讀也可寫。

隨機文件與順序文件的讀寫操作類似,但通常把需要讀寫的記錄中的各字段放在一個記錄類型中,同時應指定每個記錄的長度。

(1)隨機文件的寫操作

隨機文件的寫操作分爲4步:

1)定義數據類型

隨機文件由固定長度的記錄組成,每個記錄含有若干個字段。可以把記錄中的各個字段放在一個記錄類型中,記錄類型用用Type……End Type定義。前面已經看到Type……End Type在標準模塊中使用。

2)打開隨機文件

與順序文件不同,打開一個隨機文件後,既可用於寫操作,又可用於讀操作。打開隨機文件的一般格式爲:

    Open "文件名稱" For Random As #文件號[Len=記錄長度]

“記錄長度”等於各字段長度之和,以字符(字節)爲單位。如果省略“Len=記錄長度”,則默認長度爲128字節。

3)將內存中的數據寫入磁盤

隨機文件的寫操作通過Put語句來實現。其格式爲:

    Put #文件號,[記錄號],變量

這裏的“變量”是除對象變量和數組變量外的任何變量(包括含有單個數組元素的下標變量)。Put語句把“變量”的內容寫入由“文件號”所指定的磁盤文件中。

說明:

“文件號”的含義同前。“記錄號”的取值範圍爲1-221-1,即1-2 147 483 647。對於用Random方式打開的文件,“記錄號”是需要寫入的編號。對於用Binary方式打開的文件(見後),“記錄號”是開始寫的字節位置。文件中的第一個字節位置爲1,第二個字節位置爲2,依次類推。如果省略“記錄號”,則寫到下一個記錄或字節位置,即最近執行Get或Put語句後或由最近的Seek函數(見後)所指定的位置。但省略“記錄號”後,逗號不能省略。例如:

    Put #2,,Filebuff

如果所寫的數據的長度小於在Open語句的Len子句中所指定的長度,Put語句仍然在記錄的邊界後寫入後面的記錄,當前記錄的結尾和下一個記錄開頭之間的空間用文件緩衝區現有的內容填充。由於填充數據的長度無法確定,因此最好使記錄長度與要寫的數據的長度相匹配。

如果要寫入的變量是一個變長字符串,則除寫入變量外,Put語句還寫入2個字節的一個描述符,因此,由Len子句所指定的記錄長度至少應比字符串的實際長度多2個字節。

如果要寫入的變量是一個可變數值類型變量(VarType值0到7),則除寫入變量外,Put語句還要寫入兩個字節用來標記變體變量的ValType。例如,當寫入ValType爲3的變體時,Put語句要寫入6個字節:其中2個字節用來把變體標記爲3(Long型),4個存放Long型數據。因此,在Len子句中指出的記錄長度至少應比存放變量所需要的實際長度多2個字節。

如果要寫入的是字符串變體(VarType 8),則Put語句要寫入2個字節用來標記VarType,2個字節用來標記字符串的長度。在這種情況下,由Len子句指定的記錄長度至少應比字符串的實際長度多4個字節。

如果要寫入的是其他類型的變量(即非變長字符串或變體類型),則Put語句只寫入變量的內容,由Len子句所指定的記錄長度應大於或等於所要寫的數據的長度。

4)關閉文件

關閉文件的操作與順序文件相同。

(2)隨機文件的讀操作

從隨機文件中讀取數據的操作與寫文件操作步驟類似,只是把第三步中的Put語句用Get語句來代替。其格式爲:

    Get #文件號,[記錄號],變量

Get語句把由“文件號”所指定的磁盤文件中的數據讀到“變量”中。

“記錄號”的取值範圍同前,它是要讀的記錄的編號。如果省略“記錄號”,則讀取下一個記錄,即最近執行Get或Put語句後的記錄,或由最近的Seek函數指定的記錄。同樣,省略“記錄號”後,逗號不能省略。例如:

    Get #1,,Filebuff

Get語句的其它說明,包括“文件號”、“變量”的含義以及在讀變長字符串、變體等變量時的一些規則,均與Put語句類似,不再重複。

下面通過一個例子說明隨機文件的讀寫操作。

例8:建立一個隨機存取的工資文件,然後讀取文件中的記錄。

爲了便於說明問題,使用如下表所示的簡單的文件結構。

姓名 單位 年齡 工資
       

按以下步驟操作:

1)定義數據類型

工資文件的每個記錄含有4個字段,其長度(字節數)及數據類型見下表。

項  目 長  度 類  型
姓名(Emname) 10 字符串
單位(Unit) 15 字符串
年齡(Age) 2 整型數
工資(Salary) 4 單精度數

根據上面規定的字段長度和數據類型,定義記錄類型。

在標準模塊中定義如下記錄類型:

Type RecordType
    EmName As String * 10
    Unit As String * 15
    Age As Integer
    Salary As Single
End Type

在窗體層定義該類型的變量:

    Dim Recordvar As RecordType

2)打開文件,並指定記錄長度

從前面可知,要建立的隨機文件的每個記錄的長度爲10+15+2+4=31個字節,因此用下面的語句打開文件:

    Open "Employee.dat" For Random As #1 Len=31

用上面的語句打開文件時,記錄的長度通過手工計算得到。當記錄含有的字段較多時,這種手工計算很不方便,也容易出錯。實際上,記錄類型變量的長度就是記錄的長度,可以通過Len函數求出來,即:

    記錄長度=Len(記錄類型變量)
            =Len(
Recordvar)

因此,打開文件的語句可以改爲:

    Open "Employee.dat" For Random As #1 Len=Len(Recordvar)

注意這裏的兩個Len的意義是不同的,等號左邊的Len是Open語句中的子句,等號右邊的Len是一個函數。

3)從鍵盤上輸入記錄中的各個字段,對文件進行讀寫操作

打開文件後,就可以輸入數據,並把數據記錄寫入磁盤文件。程序如下:

Recordvar.EmName = InputBox("職工姓名:")
Recordvar.Unit = InputBox("所在單位:")
Recordvar.Age = InputBox("職工年齡:")
Recordvar.Salary = InputBox("職工工資:")
RecordNumber = RecordNumber + 1
Put #1, , Recordvar

用上面的程序段可以把一個記錄寫入磁盤文件Employee.dat。把這段程序放在循環中,就可以把指定數量的記錄寫入文件中。不必關閉文件,就可以從文件中讀取記錄。例如:

    Get #1,,Recordvar

4)關閉文件

以上是建立和讀取工資文件的一般操作,在具體編寫程序時,應設計好文件的結構。

下面是完整的程序。

在標準模塊中定義如下記錄類型:

Type RecordType
    EmName As String * 10
    Unit As String * 15
    Age As Integer
    Salary As Single
End Type

在窗體層定義該記錄類型變量和其它變量:

    Dim Recordvar As RecordType
    Dim Position As Integer
    Dim RecordNumber As Integer

編寫如下通用過程,執行輸入數據及寫盤操作:

Sub File_Write()
    Do
        Recordvar.EmName = InputBox("職工姓名:")
        Recordvar.Unit = InputBox("所在單位:")
        Recordvar.Age = InputBox("職工年齡:")
        Recordvar.Salary = InputBox("職工工資:")
        RecordNumber = RecordNumber + 1
        Put #1, RecordNumber, Recordvar
        aspect = InputBox("More(Y/N)?")
    Loop Until UCase(aspect) = "N"
End Sub

隨機文件中讀數據操作:

隨機文件建立後,可以從文件中讀取數據。從隨機文件中讀數據有兩種方法:一種是順序讀取,一種是通過記錄號讀取。由於順序讀取不能直接訪問任意指定的記錄,因而速度較慢。

編寫如下通用過程,執行順序讀文件操作:

Sub File_Read1()
    Cls
    FontSize = 12
    For i = 1 To RecordNumber
        Get #1, i, Recordvar

        Print Recordvar.EmName, Recordvar.Unit,
        Print Recordvar.Age, Recordvar.Salary, Loc(1)
    Next i
End Sub

 

該過程從前面建立的隨機文件Employee.dat中順序地讀出全部記錄,從頭到尾讀取,並在窗體上顯示出來。

關於Loc函數:
格式:LOC(文件號)
功能:返回由“文件號”指定的文件的當前讀寫位置。格式中的“文件號”是在Open語句中使用的文件號。

隨機文件的主要優點之一,就是可以通過記錄號直接訪問文件中任一個記錄,從而可以大大提高存取速度。在用Put語句向文件寫記錄時,就把記錄號賦給了該記錄。在讀取文件時,通過把記錄號放在Get語句中可以從隨機文件取回一個記錄。

下面是通過記錄號讀取隨機文件Employee.dat中任一記錄的通用過程:

Sub File_Read2()
    Getmorerecords = True
    Cls
    FontSize = 12
    Do
        Recordnum = InputBox("Enter record number for part you want to see(0 to end):")
        If Recordnum > 0 And Recordnum <= RecordNumber Then
            Get #1, Recordnum, Recordvar
            Print Recordvar.EmName; ""; Recordvar.Unit; "";
            Print Recordvar.Age; ""; Recordvar.Salary; ""; Loc(1)
            MsgBox "單擊“確定”按鈕繼續"
        ElseIf Recordnum = 0 Then
            Getmorerecords = False
        Else
            MsgBox "Input value out of range,re-enter it"
        End If
    Loop While Getmorerecords
End Sub

該過程在Do……Loop循環中要求輸入要查找的記錄號。如果輸入的記錄號在指定的範圍內,則在窗體上輸出相應記錄的數據;當輸入的記錄號爲0時結束程序;如果輸入的記錄號不在指定的範圍內,則顯示相應的信息,並要求重新輸入。

上述三個通用過程分別用來建立隨機文件、用順序方式或通過記錄號讀取文件記錄。

在下面的窗體事件過程中調用這三個過程:

Private Sub Form_Click()
    Open "c:/temp/employee.dat" For Random As #1 Len = Len(Recordvar)
    RecordNumber = LOF(1) / Len(Recordvar)
    Newline = Chr(13) + Chr(10)
    msg$ = "1.建立文件"
    msg$ = msg$ + Newline + "2.順序方式讀記錄"
    msg$ = msg$ + Newline + "3.通過記錄號讀文件"
    msg$ = msg$ + Newline + "4.刪除記錄"
    msg$ = msg$ + Newline + "0.退出程序"
    msg$ = msg$ + Newline + Newline + "請輸入數字選擇:"
Begin:
    resp = InputBox(msg$)
    Select Case resp
    Case 0
        Close #1
        End
    Case 1
        File_Write
    Case 2
        File_Read1
        MsgBox "單擊“確定”按鈕繼續"
    Case 3
        File_Read2
    Case 4   
   
'Deleterec
    End Select
GoTo Begin
End Sub

上述程序運行後,單擊窗體,在顯示的輸入對話框(如下圖)中輸入0-3(暫不輸入4)之間的數字,即可調用相應的通用過程執行隨機文件的讀寫操作。

該程序可以執行4種操作,即寫文件、順序讀文件、通過記錄號讀文件和刪除文件中指定的記錄。其中刪除記錄的操作將在後面介紹。

[程序演示]        [程序下載]

(3)隨機文件中記錄的增加與刪除

1)增加記錄

在隨機文件中增加記錄,實際上是在文件的末尾附加記錄。其方法是,先找到文件最後一個記錄的記錄號,然後把要增加的記錄寫在它的後面。

前面的通用過程File_Write具有建立文件和增加記錄兩種功能。也就是說,如果打開一個已經存在的文件,則寫入的新記錄將附加到該文件後面。

運行前面的程序,出現對話框後鍵入1,並單擊“確定”按鈕,然後再輸入幾個記錄數據。

輸入結束後,回到選擇對話框,鍵入2並“確定”後,將在窗體上顯示文件中的所有記錄,可以看出新增加的記錄已附在原來記錄的後面。

2)刪除記錄

在隨機文件中刪除一個記錄時,並不是真正刪除記錄,而是把下一個記錄重寫到要刪除的記錄上,其後的所有記錄依次前移。例如前面建立的文件有4個記錄(爲便於操作,簡單的輸入):

    張三    辦公室    35    850
   
李四    財務處    32    780
   
王五    供銷科    36    810
   
徐六    人事科    42    890

假定要刪除第二個記錄“李四    財務處    32    780”。其方法是:將第三個記錄寫到第二個記錄上,第四個記錄寫到第三個記錄上,其內容變爲:

    張三    辦公室    35    850

    王五    供銷科    36    810
   
徐六    人事科    42    890
   
徐六    人事科    42    890

 

文件中仍有4個記錄,原來的第二個沒有了,最後兩個記錄相同。也就是說,最後一個記錄是多餘的。爲了解決這個問題,可以把原來的記錄個數減1,由4個變爲3個。這樣,當再向文件中增加記錄時,多餘的記錄即被覆蓋。

根據上面分析,編寫刪除記錄的通用過程如下:

Sub Deleterec(position As Integer)  '參數position是要刪除的記錄的記錄號
    repeat:
        Get #1, position + 1, Recordvar
        If Loc(1) > RecordNumber Then GoTo finish
        Put #1, position, Recordvar
        position = position + 1
    GoTo repeat
    finish:
    RecordNumber = RecordNumber - 1
End Sub

上述過程用來刪除文件中的指定的記錄,參數position是要刪除的記錄的記錄號。該過程用後面的記錄覆蓋前面要刪除的記錄,並將其後的記錄依次前移,移動完成後,最後的記錄號減1。

該過程是前面程序的一部分,可以在前面的事件過程中調用。把事件過程中的“Case 4”後面的部分改爲:

p = InputBox("輸入記錄號:")
Deleterec(p)

運行程序後,在選擇對話框中輸入4,將顯示一個對話框,要求輸入要刪除的記錄的記錄號。輸入2並單擊“確定”按鈕,第二個記錄即被刪除,回到選擇對話框。此時如果輸入2,單擊“確定”按鈕,即可看到第二個記錄已被刪除。

[程序演示]        [程序下載]

(4)用控件顯示和修改隨機文件

前面介紹了隨機文件的讀寫及修改操作。執行這些操作的程序是用VB編寫的,然而其操作方法和顯示方法與傳統語言沒什麼區別。如果能結合VB的控件來顯示和修改隨機文件中的數據,效果要好得多。下面通過一個例子說明它的實現方法。

例9:編寫程序,用控件顯示和修改隨機文件中的數據。

我們仍然使用前面建立的“employee.dat”文件來設計程序。按以下步驟操作:

1)在標準模塊中定義記錄類型(同前)。

2)在窗體模塊中定義變量(同前)。

3)在窗體上添加控件,並設置屬性,如下:

其中4個文本框是一個文本框控件數組的4個元素,其控件組名是Text1,並將其Text屬性設置爲空白。

4)編寫代碼

編寫通用過程:

Sub display()
    Get #1, position, Recordvar
    Text1(0).Text = Recordvar.EmName
    Text1(1).Text = Recordvar.Unit
    Text1(2).Text = Recordvar.Age
    Text1(3).Text = Recordvar.Salary
End Sub

編寫事件過程:

打開文件:

Private Sub Command3_Click()
    Open "c:/temp/employee.dat" For Random As #1 Len = Len(Recordvar)
    RecordNumber = LOF(1) / Len(Recordvar)
    position = 1
    display
End Sub

該過程用來打開文件,計算出最後一個記錄的記錄號,並把當前記錄號設置爲1,然後調用display過程顯示記錄的內容。

顯示前一個記錄:

Private Sub Command1_Click()
    If position > 1 Then
        position = position - 1
        display
    ElseIf position = 1 Then
        MsgBox "這是第一個記錄"
    End If
End Sub

該事件過程用來顯示當前記錄的前一個記錄。由於第一個記錄沒有“前一個記錄”,因此如果當前記錄是第一個記錄,則單擊“前一記錄”按鈕時將顯示相應的信息。

顯示下一個記錄: 

Private Sub Command2_Click()
    If position < RecordNumber Then    
        position = position + 1
        display
    ElseIf position = RecordNumber Then
        msg$ = "這是最後一個記錄!" + Chr(13) + Chr(10)
        msg$ = msg$ + "是否關閉文件?"
        resp = MsgBox(msg$, 36, "請選擇")
        If resp = 6 Then
            Close #1
            End
        End If
    End If
End Sub

該事件過程用來顯示當前記錄的下一個記錄,如果當前記錄是最後一個記錄,則單擊“下一記錄”按鈕時將顯示相應的信息,並詢問用戶是否關閉文件。如果單擊對話框中的“Yes”按鈕,則關閉文件,結束程序運行,否則繼續運行。

修改記錄: 

Private Sub Command4_Click()
    Recordvar.EmName = Text1(0).Text
    Recordvar.Unit = Text1(1).Text
    Recordvar.Age = Text1(2).Text
    Recordvar.Salary = Text1(3).Text
    Put #1, position, Recordvar
End Sub

該事件過程用來修改記錄。單擊需要修改的字段所在的文本框,把光標移到該文本框中,就可修改該文本框的內容。修改後單擊“數據修改”命令按鈕,就可以把修改後的記錄寫入文件中,並覆蓋原來的記錄。

退出程序:

Private Sub Command5_Click()
    End
End Sub

{程序演示]        [程序下載]

3、二進制文件

利用二進制存取可以獲取任一文件的原始字節,即不僅能獲取ASCII文件,而且能獲取非ASCII文件的原始字節。這樣,用戶就可以讀取或修改以非ASCII格式存盤的文件,例如可執行文件(.exe)

用下面的語句可以打開二進制輸入/輸出文件:

    Open 文件說明 For Binary As #文件號

爲二進制存取打開的文件作爲非格式化的字節序列處理。可以把記錄讀或寫到以二進制方式打開的文件中,但文件本身不必處理成定長記錄。實際上,二進制文件本身不必涉及記錄,除非把文件中的每個字節看成一個記錄。

通過使用二進制型訪問可使磁盤空間的使用降到最小。因爲二進制文件不需要固定長度的字段(在二進制文件中每個記錄只佔用所需字節,所以不必爲字段指定長度),類型聲明語句可以省略字符串長度參數。當記錄中的字段需要包含大段文字時,使用二進制文件可以節省大量的磁盤空間。

(1)二進制存取與隨機存取

二進制文件與隨機文件的存取操作類似,這主要表現在以下兩個方面:

1)不需要在讀與寫之間切換。在執行Open語句打開文件後,對該文件既可以讀,也可以寫,並且利用二進制存取可以在一個打開的文件中前後移動。

2)讀寫隨機文件的語句也可以用於讀寫二進制文件,即:

    Get│Put #文件號,[位置],變量

在這裏,“變量”可以是任何類型,包括變長字符串和記錄類型;“位置”指明下一個Get或Put操作在文件的什麼地方進行。二進制文件中的“位置”相對於開頭而言。即第一個字節的“位置”是1,第二個字節的“位置”是2,等等。如果省略“位置”,則Get和Put操作將文件指針從第一個字節到最後一個字節順序進行掃描。

Get語句從文件中讀出的字節數等於“變量”的長度;同樣Put語句向文件中寫入的字節數與“變量”的長度相同。例如,如果“變量”爲整型,則Get語句就把讀取的2個字節賦給“變量”;如果“變量”爲單精度型,則Get語句就讀取4個字節。因此,如果Get和Put語句中沒有指定“位置”,則文件指針每次移過一個與“變量”長度相同的距離。

二進制文件與隨機文件也有不同之處,主要是:二進制存取可以移到文件中的任一字節位置上,然後根據需要讀、寫任意個字節;而隨機存取每次只能移到一個記錄的邊界上,讀取固定個數的字節(一個記錄的長度)。

二進制文件只能通過Get語句或Input#函數讀取數據,而Put則是向以二進制方式打開的文件中寫入數據的唯一方法。

爲了可以同時使用隨機文件和二進制文件的優點,可以使用這樣的組合--當字段的長度固定或者長度變化不大時,可以將這些字段存儲在隨機文件中,而對於長度變化很大的字段,可以保存在二進制文件中,而在隨機文件的記錄中設置一個字段指定它在二進制文件中的位置即可。這樣,既可以利用隨機文件的方便快捷,又可以大大節省許多磁盤空間。

(2)文件指針

在二進制文件中,可以把文件指針移到文件中任意位置。文件指針的定位通過Seek語句來實現。其格式爲:

    Seek #文件號,位置

Seek語句用來設置文件中下一個讀或寫的位置。“文件號”的含義同前,“位置”是一個數值表達式,用來指定下一個要讀寫的位置,其值在1—231-1的範圍內。

說明:

1)對於用Binary,Input,Output或Append方式打開的文件,“位置”是從文件開頭到“位置”爲止的字節數,即執行下一個操作的地址,文件第一個字節的位置爲1。對於用Random方式打開的文件,“位置”是一個記錄號。

2)在Get或Put語句中的記錄號優先於由Seek語句確定的位置。此外,當“位置”爲0或負數時,將產生出錯信息“錯誤的記錄號”。當Seek語句中的“位置”在文件尾之後時,對文件的寫操作將擴展該文件。

Seek語句配合的使用的是Seek函數。其格式爲:

    Seek(文件號)

該函數返回文件指針的當前位置。由Seek函數返回的值在1—231-1的範圍內。

對於用Binary,Input,Output或Append方式打開的文件,Seek函數返回文件中的字節位置(產生下一個操作的位置),對於用Random方式打開的文件,Seek函數返回下一個要讀或寫的記錄號。

在訪問二進制文件時,Seek函數與Loc函數給出相似的結果。所不同的是Loc函數返回的是最近一次讀寫過的字節的位置,而Seek函數返回的則是下一次要讀或寫的字節位置。

對於順序文件,Seek語句把文件指針移到指定的字節位置上,Seek函數返回有關下次將要讀寫的位置信息;對於隨機文件,Seek語句只能把文件指針移到一個記錄的開頭,而Seek函數返回的是下一個記錄號。

例10:編寫程序,建立一個二進制文件,然後用Seek函數返回各項數據的位置。

在窗體上添加3個命令按鈕,Caption屬性分別爲“建立文件”、“返回位置”和“退出”,然後對3個按鈕編寫如下事件過程:

“建立文件”事件過程:

Private Sub Command1_Click()
Dim stuname As String * 10
FileName$ = InputBox("Enter file name:")
Open FileName For Binary As #1
Do
stuname = InputBox("請輸入學生的姓名:")
Put #1, , stuname
resp$ = InputBox("繼續輸入嗎?(Y/N)")
Loop While UCase(resp) = "Y"
Close #1
End Sub

該過程要求輸入一個文件名,並把它作爲二進制文件打開(該文件如不指定路徑,則默認位置在VB98文件夾下,可以用記事本查看),然後向該文件中寫入數據(學生姓名)。每輸入完一個姓名,程序詢問是否繼續輸入,鍵入“Y”繼續,否則結束輸入。

“返回位置”事件過程:

Private Sub Command2_Click()
Dim stuname As String * 10
FileName$ = InputBox("Enter file name:")
Open FileName For Binary As #1
flen = LOF(1)
For i = 1 To flen Step 10
Get #1, , stuname
x = Seek(1)
Print stuname, x
Next i
Close #1
End Sub

Seek函數返回的是下一個要讀出的字節位置。由於變量的長度爲10個字節,因此第一次返回的字節位置爲11,第二次爲21,依次類推。

“退出”事件過程: 

Private Sub Command3_Click()
End
End Sub

[程序演示]        [程序下載]

 

發佈了0 篇原創文章 · 獲贊 4 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章