7.5.7. Tệp truy cập trực tiếp
PASCAL chuẩn chỉ định nghĩa một kiểu tệp truy nhập tuần tự. Tuy nhiên các bộ nhớ ngoài như đĩa từ, đĩa quang, . . có thể cho phép tính toán toạ độ của một phần tử bất kỳ trong tệp (vì độ dài các phần tử là bằng nhau), do đó có thể truy cập trực tiếp vào một phần tử mặc dù cấu tạo logic của tệp vẫn là dạng tuần tự. Trong TURBO PASCAL để truy nhập trực tiếp vào phần tử của tệp ta dùng thủ tục SEEK, cú pháp:
SEEK( biếntệp, k );
Đặt con trỏ tệp vào phần tử thứ k trong tệp. Thủ tục này cho phép truy xuất trực tiếp một phần tử của tệp mà không phải thực hiện tuần tự từ đầu tệp.
Ví dụ 7.66: đọc phần tử thứ 10 của tệp DLIEU.DAT và gán cho biến nguyên i rồi in giá trị của i:
Seek(F1, 10);
Read(F1, i);
Write(i);
Chương trình sau minh hoạ thủ tục SEEK
Program Vidu_7_66_Seek;
Var I,N : Integer;
Ch : Char;
f : File Of Integer;
Begin
Writeln('DI CHUYEN CON TRO TEP DEN PHAN TU THU N');
Writeln('-------------------------------------------');
Writeln;
Assign(f,'SoNguyen.DAT');
Reset(f);
Write('-Can tim phan tu thu: ');
Readln(n);
Seek(f,(n-1));
Read(f,i);
Writeln;
Writeln('-Phan tu thu: ',n,' co tri = ',i);
Writeln;
Write('-Co can sua khong ? (C/K) ');
Readln(Ch);
If Ch in ['C','c'] Then
Begin
Seek(f,n-1);
Write('-Nhap so can sua: ');
Readln(i);
Write(f,i);
End;
Writeln;
Write('Da sua va ghi lai vao tep, bam de xem lai');
Readln;
Seek(f,0);
While Not EOF(f) Do
Begin
Read(f,i);
Writeln(i);
End;
Writeln;
Seek(f,0);
Read(f,i);
Writeln('-Phan tu dau tien co tri= ',i);
Writeln;
Seek(f,Filesize(f)-1);
Read(f,i);
Writeln('-Phan tu cuoi cung co tri = ',i);
Writeln;
Writeln(' Bam ...');
Readln;
Close(f);
End.
7.5.8. Các thao tác khác với tệp
* Các hàm và thủ tục xử lý tệp
THỦ TỤC VÀ HÀM
|
Ý NGHĨA
|
Hàm FileSize(Biếntệp)
|
Cho số phần tử của biến tệp. Hàm sẽ cho giá trị 0 khi tệp rỗng
|
Hàm FilePos(Biếntệp)
|
Cho biết vị trí hiện tại của con trỏ tệp
( phần tử đầu tiên của tệp được đánh số là 0 )
|
Hàm EOF(Biếntệp)
|
Cho giá trị là True nếu con trỏ tệp ở vị trí cuối của tệp, trái lại là False. Hàm này thường dùng để kiểm tra xem đã đọc hết dữ liệu trong tệp chưa ?
|
Hàm EOLn(Biếntệp)
|
Cho giá trị là True nếu con trỏ tệp ở vị trí cuối dòng của tệp văn bản, trái lại là False. Hàm này thường dùng để kiểm tra xem đã đọc hết dòng văn bản trong tệp chưa ?
Hàm này chỉ dùng với tệp văn bản
|
Truncate(Biếntệp);
|
Cắt tệp từ vị trí hiện tại của tệp (cửa sổ tệp).
|
Erase(Biếntệp)
|
Thủ tục này dùng để xoá tệp trên đĩa có tên đã gán vào biến tệp.
Không được xoá tệp khi tệp đang mở .
|
Rename(Biếntệp,Str)
|
Thủ tục này dùng để đổi tên biến tệp trên đĩa thành tệp có tên mới kiểu String chứa trong Xâu kí tự Str .
Không được đổi tên tệp khi tệp đang mở và tên mới không được trùng với tên tệp đã có trên đĩa đang làm việc .
Ví dụ đổi tên tệp có tên là NTL02.pas thành NTL02.sl :
Assign(Biến tệp,’NTL02.pas');
Rename(Biến tệp,'NTL02.sl');
|
Ví dụ 7.67: Tạo tệp TEST.INT có 10 số nguyên, sau đó hiển thị ra màn hình kích thước tệp, các phần tử của tệp.
Program Ham_Tep;
Var f : File Of Integer;
i,j,k,v : Integer;
Begin
Writeln('SU DUNG CAC HAM TEP ');
Writeln('------------------------');
Assign(f,'TEST.INT');
Rewrite(f);
For i := 1 To 10 Do
Write(f,i);
Writeln;
Writeln('Da tao tep TEST.INT co 10 so nguyen');
Write('Bam de xem noi dung tep TEST');
Readln;
Reset(f);
While Not EOF(f) Do
Begin
Read(f,i);
Writeln(i);
End;
Writeln;
k:= Filesize(f);
Writeln('-Kich thuoc tap tin= ',k,' phan tu');
Write('Bam de di chuyen den phan tu thu 5 ');
Readln;
Seek(f,5-1);
Read(f,i);
Writeln;
Writeln('-Phan tu thu 5 co tri = ',i);
v := Filepos(f);
Writeln;
Writeln('-Vi tri con tro tep hien gio o phan tu thu: ',v);
Writeln;
Write('Bam de xem cac phan tu con lai ');
Readln;
While Not EOF(f) Do
Begin
Read(f,i);
Writeln(i);
End;
Writeln;
If EOF(f) Then
Writeln('-Da ket thuc tep')
Else
Writeln('-Chua ket thuc tep');
Writeln;
Write(' Bam de ket thuc ');
Readln;
Close(f);
Erase(f);
End.
Ví dụ 7.68: Chương trình cắt tệp TEST.INT
Program Cat_Tep;
Var f : File Of Integer;
i,j : Integer;
Begin
Writeln('CAT TEP BANG THU TUC TRUNCATE');
Writeln('---------------------------------');
Writeln;
Assign(f,'TEST.INT');
Rewrite(f);
For i := 1 To 10 Do
Write(f,i);
Writeln;
Writeln('Da tao tep TEST.INT co 10 so nguyen');
Write('Bam de xem noi dung tep TEST');
Readln;
Reset(f);
While Not EOF(f) Do
Begin
Read(f,i);
Writeln(i);
End;
Reset(f);
Writeln;
Write(' Bam de cat 5 phan tu ');
Readln;
Reset(f);
For i := 1 To 5 Do
Read(f,i);
Truncate(f);
Writeln;
Writeln(' Da cat 5 phan tu cua tep');
Write('Bam de xem noi dung tep con lai ');
Readln;
Reset(f);
While Not EOF(f) Do
Begin
Read(f,i);
Writeln(i);
End;
Writeln;
Write(' Bam de ket thuc ');
Readln;
Close(f);
Erase(f);
End.
Ví dụ 7.68: Chương trình minh hoạ thủ tục xoá tệp
Program Xoa_Tep;
Var f : File Of String;
Ten : String;
Begin
Writeln('THU TUC ERASE, XOA TEP');
Write('-Cho biet ten tap tin can xoa: ');
Readln(Ten);
Assign(f,Ten);
{$I-}
Reset(f);
If IOResult <> 0 Then
Writeln(' Khong co tep: ',Ten,' tren dia')
Else
begin
Erase(f);
Writeln;
Write(' Da xoa tep, bam . . . ');
End;
Readln;
Close(f);
End.
* Bẫy lỗi khi mở tệp:
Đặt vấn đề
Khi thực hiện thao tác mở tệp để đọc / ghi có thể bị lỗi nếu:
- mở tệp chưa tồn tại trên đĩa, tên sai ...
- hết chỗ trên đĩa để ghi thêm vào tệp.
TurboPascal cung cấp chỉ thị để trình biên dịch thêm các mã lệnh thực hiện kiểm tra lỗi trong quá trình thực hiện đọc / ghi tệp mà dưới đây sẽ gọi ngắn gọn là chỉ thị kiểm tra I/O.
{ $ I + }: bật (mở) việc kiểm tra I/O. Nếu gặp lỗi I/O chương trình sẽ báo lỗi và dừng lại. Đây là chế độ mặc định.
{ $ I - }: tắt việc kiểm tra I/O. Chương trình không dừng dù có lỗi I/O. Tuy nhiên nó sẽ bỏ qua (treo, tạm dừng) tất cả các thủ tục vào/ra sau đó cho đến khi gặp lời gọi hàm IOResult. IOResult là hàm trả về mã lỗi khi thực hiện các thao tác đọc ghi ra đĩa. Nếu công việc thành công thì mã lỗi là 0. Trái lại, mã lỗi là một số khác không.
Sử dụng cơ chế kiểm tra I/O có thể thực hiện việc bẫy lỗi khi mở tệp, nhất là tiến hành mở tệp mới an toàn, tránh việc vô tình xoá mất tệp cùng tên khi mở tệp mới để viết vào bằng thủ tục Rewrite.
Các bước để mở tệp an toàn.
Tắt chế độ kiểm tra và thử mở tệp ra để đọc.
Gọi hàm IOResult.
Nếu IOResult bằng 0, nghĩa là mở tệp thành công tức là đã có tệp cùng tên. Cần thông báo cho người dùng biết để xử lý, nhập lại tên khác chẳng hạn.
Nếu IOResult khác không nghĩa là chưa có tệp nào có tên như thế. Có thể yên tâm tạo tệp bằng lệnh Rewrite.
Ví dụ 7.70:
Assign( biến tệp , tên tệp);
{$I-}
Reset( biến tệp );
{$I+}
If IOResult <> 0 then {không có tệp nào trùng tên}
Begin
Writeln(' Ban muon tao tep moi ? Enter=Yes ');
if ReadKey = #13 then Rewrite( biến tệp )
else exit;
end;
Else
Begin
Writeln(' Da co tep trung ten '); ....
End;
Việc tắt chế độ kiểm tra I/O bằng chỉ thị {$I-} trước câu lệnh Reset là để tránh báo lỗi và dừng chương trình theo mặc định khi mở tệp chưa có trên đĩa.
Chia sẻ với bạn bè của bạn: |