Dữ Liệu Kiểu Tệp: GIỚI THIỆU VÀ SỬ DỤNG (p2) MỞ TỆP VÀ ĐỌC ...

Một chương trình muốn sử dụng các dữ liệu đã được chứa trong một tệp đầu tiên chương trình phải mở tệp đó ra để đọc. Các thủ tục dùng cho công việc này như sau :

·MỞ TỆP ĐỂ ĐỌC :

Assign ( Biến_tệp, Tên_tệp ) ;

Reset ( Biến_tệp ) ;

hay Assign ( FileVar, FileName ) ;

Reset ( FileVar ) ;

Khi chạy, chường trình sẽ đọc phần tử dữ liệu tại vị trí cửa sổ đang trỏ. Sau lệnh Reset, nếu tệp không rỗng thì cửa sổ bao giờ cũng trỏ vào phần tử đầu tiên của tệp và chương trình sẽ copy phần tử của tệp được trỏ sang biến đệm cửa sổ.

·ĐỌC DỮ LIỆU TỪ TỆP :

Việc đọc các phần tử từ tệp ra sau khi mở tệp đựoc thực hiện bằng thủ tục READ

Cách viết :

Read ( Biến_tệp, các biến ) ;

hoặc Read ( FileVar, Var1, Var2,... VarN ) ;

Thực hiện : đọc các giá trị tại vị trí cửa sổ đang trỏ (nếu có) gán sang biến tương ứng cùng kiểu. Sau đó cửa sổ dịch chuyển sang vị trí tiếp theo và đọc giá trị cho biến khác. Cứ thế đọc cho đến biến VarN.

Một điều cần lưu ý là trong thủ tục Read ta chỉ có thể đọc giá trị của tệp để gán giá trị cho các biến và chỉ cho các biến mà thôi. Không như trong thủ tục ghi vào tệp, các tham số thực là các Item ( hằng, biến, biêu thức ).

Việc đọc một phần tử của tệp còn cần có một điều kiện : phải thử xem tệp có còn phần tử không tức là cửa sổ chưa trỏ đến EOF. Hàm chuẩn EOF sẽ báo cho biết : nếu cửa sổ trỏ vào cuối tệp thì EOF(Biến_tệp) = True, còn nếu cửa sổ chưa trỏ vào phần tử cuối của tệp thìEOF(Biến_tệp) = False. Do vậy trước khi làm một thao tác gì để đọc tệp gán cho biến X, cần phải thử xem tệp đó đã kết thúc chưa bằng câu lệnh :

If Not Eof ( Biến_tệp ) Then Read ( Biến_tệp, X ) ;

hoặc nếu muốn đọc các phần tử của tệp :

While Not Eof ( Biến_tệp ) Do

Begin

Read ( Biến_tệp, X ) ; (* Đọc các phần tử của tệp *)

................... (* Xử lý biến X, nếu cần *)

End ;

Nếu cửa sổ đã trỏ đến phần Eof mà chương trình vẫn cố tình đọc thì sẽ gặp sai và máy sẽ báo lỗi, sau đó chương trình dừng lại.

Công việc cuối cùng kết thúc việc đọc tệp là đóng tệp lại với thủ tục giống như khi tạo tệp mới :

Close ( Biến_tệp ) ;

Bây giờ chúng ta lấy ví dụ cụ thể. Giả sử tồn tại một tệp có tên là ‘Nguyen.dat’ được tạo ra bằng các thủ tục mở tệp cất dữ liệu như ở trên đã mô tả. Ta phải đọc ra giá trị thứ nhất và thứ ba của tệp và gán cho hai biến A, B tương ứng. Giả sử tệp không rỗng và chứa ít nhất 3 phần tử để ta không phải dùng phép thử Eof.

Ví dụ 3 :

Program DOC_TEP_1 ;

Var

A, B : Integer ;

F : File Of Integer ;

BEGIN

Assign ( F, 'Nguyen.dat' ) ;

Reset ( F ) ;

Read ( F, A ) ; (* Đọc phần tử thứ nhất của tệp và chứa vào biến A *)

Read ( F, B ) ; (* Đọc phần tử thứ hai của tệp và chứa vào biến B *)

Read ( F, B ) ; (* Đọc phần tử thứ ba của tệp và chứa vào biến B,

lúc này B không giữ giá trị của phần tử thứ hai nữa *)

Close ( F ) ;

END.

Sở dĩ phải đọc cả phần tử thứ hai là vì đây là tệp có cấu trúc tuần tự, muốn đọc phần tử thứ ba thì phải đọc qua phần tử thứ hai.

Ví dụ tiếp theo minh họa việc đọc tất cả các phần tử của một tệp các số nguyên nào đó và ghi ra màn hình giá trị các số nguyên đó và cuối cùng ghi ra cả số phần tử của tệp. Tên tệp sẽ được xác định lúc chạy chương trình chứ không có ngay từ lúc lập trình. Do không biết tệp kết thúc ở đâu nên ta phải dùng phép thử Not Eof.

Ví dụ 4 :

Program DOC_TEP_2 ;

Var

I : Integer ;

SoPhanTu : Integer ;

F : File Of Integer ;

FileName : String [ 20 ] ;

BEGIN

Write ( ' Ten tep chua cac so nguyen : ' ) ;

Readln ( FileName ) ;

Assign ( F, FileName ) ;

Reset ( F ) ;

SoPhanTu := 0 ;

While Not Eof ( F ) Do

Begin

Read ( F, I ) ; (* Đọc một phần tử tệp ra biến I *)

Writeln ( I ) ;

SoPhanTu := SoPhanTu + 1 ; (* Đếm số phần tử *)

End ;

Close ( F ) ;

Writeln ( ' So phan tu cua tep ', FileName, ' la ', SoPhanTu ) ;

END.

Ví dụ tiếp theo minh họa việc Copy từ một tệp các số nguyên gọi tệp nguồn sang một tệp khác. Chương trình được cho dưới dạng thủ tục.

Ví dụ 5 :

Type

F : File Of Integer ;

Var

FS, FD : F ; (* FS : FileSource ( File nguồn ), FD : File Destination ( File đích ) *)

Name1, Name2 : String [ 30 ] ;

(* ------------------------------------------------------------- *)

Procedure CopyFile ( Var Source, Destination : F ) ;

Var

I : Integer ;

Begin

Reset ( Source ) ;

Rewrite ( Destination ) ;

While Not Eof ( Source ) Do

Begin

Read ( Source, I ) ;

Write ( Destination, I ) ;

End ;

Close ( Source ) ;

Close ( Destination ) ;

End ;

(* ------------------------------------------------------------- *)

BEGIN

Write ('Copy form file ') ; Readln ( Name1 ) ;

Write (' to file ') ; Readln ( Name2 ) ;

Assign ( FS, Name1 ) ;

Assign ( FD, Name2 ) ;

CopyFile ( FS, FD ) ;

Writeln (' Copy successful ') ;

END.

* Tệp với các phần tử của tệp là dữ liệu có cấu trúc :

Các ví dụ trên mới chỉ đơn cử các chương trìng xử lý các tệp có các phần tử là các dữ liệu đơn giản như Integer, Real... Tệp cũng có thể dùng mảng hoặc bản ghi như các phần tử của tệp (xem tệp FNS, F6 ở đầu chương).

Ví dụ với FNS, các phần tử của tệp FNS là bản ghi thì để ghi vào tệp ta phải dùng :

Write ( FNS, Nguoi ) ;

chứ không thể ghi riêng rẽ từng phần, từng trường :

Write ( FNS, Nguoi.ten ) ;

TỆP TRUY NHẬP TRỰC TIẾP

Pascal chuẩn chỉ định nghĩa một kiểu tệp : tệp truy nhập tuần tự. Các bộ nhớ ngoài như đĩa mềm, đĩa cứng... cho phép có thể tính toán tọa độ của một phần tử bất kỳ của tệp vì độ dài của các phần tử trong tệp là như nhau. Điều đó cho phép truy nhập trực tiếp vào tệp mặc dù cấu tạo logic của tệp vẫn là dạng tuần tự tức là phần tử nọ xếp sau phần tử kia. Trong Pascal có một thủ tục để truy nhập trực tiếp : SEEK.

* Cách viết : Seek ( FileVar, No );

với No là số thứ tự của phần tử trong tệp. Cần lưu ý là phần tử đầu tiên của tệp được đánh số 0.

Theo thủ tục này, máy sẽ đặt cửa sổ của tệp vào phần tử thứ No. Sau đó ta chỉ việc dùng các thủ tục Read để đọc phần tử đó ra hoặc Write để đặt giá trị mới vào. Như vậy ta có thể cập nhật một tệp một cách dễ dàng.

Ví dụ: Giả sử một tệp đã chứa 100 số nguyên từ 1 đến 100. Ta phải kiểm tra xem phần tử thứ hai (đếm từ 0) của tệp có giá trị bằng 3 không, nếu không bằng 3 thì phải sửa lại :

Var

F : File Of Integer ;

Ch : Char ;

I : Integer ;

BEGIN

...........

Assign ( F, 'Songuyen.dat' ) ;

Reset ( F ) ;

Seek ( F, 2 ) ; (* đặt cửa sổ vào vị trí thứ 3 *)

Read ( F, I ) ;

Writeln ( ' I = ', I ) ;

If I <> 3 Then Write ( F, 3 ) ; (* nếu không bằng 3 thì sửa lại *)

Close( F ) ;

END.

THỦ TỤC VÀ HÀM XỬ LÍ TỆP

FileSize ( FileVar ) :

Hàm cho số phần tử của tệp FileVar. FileSize nhận giá trị 0 khi tệp rỗng, không có phần tử nào.

FilePos ( FileVar ) :

Hàm cho vị trí tức thời của con trỏ tệp ( cửa sổ ) của tệp FileVar. Phần tử đầu tiên là phần tử số 0.

Ứng dụng: một tệp đã tồn tại chỉ có thể cho lớn lên tức là thêm số phần tử vào tệp bằng cách đặt thêm phần tử mới vào vị trí cuối cùng của tệp. Vì vậy con trỏ tệp có thể đặt vào vị trí cuối tệp bằng lệnh sau :

Seek ( FileVar, FileSize ( FileVar ) ) ;

Trong ví dụ ở bài trước, nếu muốn thêm số liệu I vào tệp F, ta viết :

Seek ( F, FileSize ( F ) ) ;

Write ( F, I ) ;

Mọi sự thay đổi vể tệp chỉ được giữ lại trên đĩa khi thực hiện thủ tục Close( F ).

Erase ( FileVar ) ;

Thủ tục xóa file trên đĩa có tên đã được ấn định với FileVar.

Ví dụ : muốn xóa file File.exe trên đĩa, ta viết :

Assign ( F, 'File.exe' ) ;

Erase ( F ) ;

Rename ( FileVar, Str ) ;

Thủ tục cho phép they đổi tên tệp thành tên chứa trong chuỗi Str. Bạn cần lưu ý là tên mới không được trùng với tên nào trên thư mục đang làm việc.

Ví dụ : muốn đổi tên tệp từ ‘File.old’ sang ‘File.new’, ta viết :

Assign ( F, 'File.old' ) ;

Rename ( F, 'File.new' ) ;

Võ Nhật Trường

Từ khóa » Câu Lệnh While Not Eof Trong Pascal