D liu kiu File
1.Khái niệm về tệp
Tệp hay tệp dữliệu là một tập hợp các dữliệu có liên quan với nhau và có
cùng kiểu đợc nhóm lại với nhau tạo thành một dãy. Chúng thờng đợc chứa trong
một thiết bị nhớ ngoài của máy tính (đĩa mềm, đĩa cứng )
Tệp dữliệu theo nghĩa rộng : có thể đó là chơng trình, có thể là số liệu, có
thể là các dữliệu khác nh kí tự, văn bản
Tệp đợc lu trữ trong bộ nhớ ngoài nh đĩa cứng, đĩa mềm Điều đó có
nghĩa là tệp đợc lu trữ để dùng nhiều lần và tồn tại ngay cả khi chơng trình kết
thúc hoặc mất điện. Vì vậy nhng dữliệu nào cần lu giữ thì chúng ta bắt buộc
phải dùng đến tệp.
Tệp là một kiểu dữliệu có cấu trúc. Định nghĩa tệp có phần nào giống
mảng ở chỗ chúng đều là tập hợp của các phần tử dữliệu cùng kiểu. Song mảng
đợc khai báo trong chơng trình với số phần tử đã xác định, còn số phần tử của tệp
không xác định khi định nghĩa
2. Cách định nghĩa tệp trong Pascal
Cách 1
TYPE
Kiểu_tệp = FILE OF kiểu_phần_tử;
Sau đó ta khai báo
VAR Biến_Tệp : Kiểu_tệp;
Cách 2 : khai báo trực tiếp
VAR
Biến_tệp : FILE OF Kiểu_phần_tử;
VD :
TYPE
FileInteger = FILE OF integer;
FileReal = FILE OF real;
FileBoolean = FILE OF Boolean;
Nhan_su = RECORD
Ten : String[30];
Tuoi : Byte;
Luong : Real;
END;
VAR
F1,F2 : FileInteger;
F3 : FileReal;
FNS : FILE OF Nhan_su;
F5 : FILE OF Char;
3.Mở tệp mới để cất dữ liệu
a. Mở tệp để ghi
Pascal dùng 2 thủ tục đi liền nhau theo thứ tự
ASSIGN (Biến_Tệp, Tên_tệp); Gán tên_tệp cho biến_tệp;
REWRITE (Biến_Tệp);
VD : ASSIGN(F1,'NGUYENTO.DAT');
REWRITE(F1);
1
Sau khi mở tệp xong, tệp sẽ rỗng vì cha có phần tử nào, cửa sổ tệp sẽ không có
giá trị xác định vì nó trỏ vào cuối tệp (EOF). Ly ý, nếu trên đĩa có tập tin trùng
với tên của tệp mở thì nó sẽ bị xoá đi.
b.Ghi các giá trị vào tệp với thủ tục WRITE
Cách viết
Write (Biến_tệp, Item1, Item2, , ItemN);
Trong đó Item1, Item2, ItemN là các hằng, biến, các biểu thức và phải có giá
trị cùng với kiểu phần tử của tệp
VD : Với I,J,K là các biến INTEGER, ta có thể viết :
Write (F1, 3, I+2*J, K, 5);
Bớc cuối cùng của việc đặt dữliệu vào tệp là đóng tệp bằng thủ tục
CLOSE (Biến_Tệp)
VD : CLOSE(F1);
4. Đọc dữliệu từ một tệp đã có
a. Mở tệp để đọc
Pascal dùng 2 thủ tục đi liền nhau theo thứ tự
ASSIGN (Biến_Tệp, Tên_tệp); Gán tên_tệp cho biến_tệp;
RESET (Biến_Tệp);
VD : ASSIGN(F1,'NGUYENTO.DAT');
RESET(F1);
Sau khi mở tệp xong, 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
b.Đọc dữliệu từ tệp
Cách viết
Read (Biến_tệp, Var1, Var2, , VarN);
Trong đó Var1, Var2, VarN chỉ có thể là các biến có giá trị cùng với kiểu
phần tử của tệp
Việc đọc một phần tử của tệp còn cần có điều kiện : phải xem tệp có còn phần
tử không, tức là cửa sổ tệp cha trỏ đến EOF. Hàm EOF(Biến_tệp)=TRUE nếu
cửa sổ tệp trỏ vào cuối tệp và EOF(Biến_tệp)=FALSE nếu cửa sổ vẫn trỏ vào
phần tử của tệp
VD : Muốn đọc tất 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);
END;
c.Bớc cuối cùng của việc đọc dữliệu từ tệp là đóng tệp bằng thủ tục
CLOSE (Biến_Tệp)
VD : CLOSE(F1);
5.Tệp truy nhập trực tiếp
Vì độ dài của các phần tử trong tệp là nh nhau nên ta có thể truy nhập trực tiếp
vào vị trí của một phần tử nào đó trong tệp bằng cách dùng SEEK
Cách viết
SEEK (Biến_Tệp, No) No là số thứ tự của phần tử trong tệp
2
Theo thủ tục này máy sẽ đặt cửa sổ tệp vào phần tử thứ No. Sau đó ta chỉ cần
dùng các thủ tục READ để đọc nó ra hoặc WRITE để đặt giá trị mới vào
6.Các thủ tục và hàm xử lí tệp của Pascal
FILESIZE (F) : cho số phần tử của tệp F
FILEPOS (F) : cho vị trí tức thời của con trỏ
ERASE (F) : xoá FILE trên đĩa có tên đã gán vào F
RENAME (F, St) : đổi tên tệp thành St (kiểu String)
7.Tệp văn bản (TEXT FILE)
a. Cách khai báo
VAR Biến_tệp : TEXT;
VD :
VAR F1,F2 : TEXT
Các phần tự của tệp kiểu TEXT là các kí tự (chữ viết) song TEXT khác với FILE
OF Char ở chỗ TEXT đợc tổ chức thành từng dòng với độ dài mỗi dòng khác
nhau nhờ có thêm các dấu hết dòng. Đó là cặp kí tự điều khiển :
- CR (Carriage Return) : nhảy về đầu dòng, mã số ASCII=13
- LF (Line Feed) : nhảy xuống dòng tiếp theo, mã số ASCII=10
Chúng đợc nhận dạng để ngăn cách giữa 2 dãy kí tự tơng ứng với 2 dòng khác
nhau
VD : Đoạn văn bản sau
VI DU
1234
HET
Máy sẽ chứa trong tệp văn bản thành một dãy nh sau :
VI DU CR LF 1234 CR LF HET EOF
b.Ghi vào tệp văn bản
Có 3 thủ tục
Write(Biến_Tệp, Item1, Item2, ItemN);
Writeln(Biến_Tệp, Item1, Item2, ItemN);
Writeln(Biến_Tệp);
Trong đó Item1, Item2, ItemN là các hằng, biến, biểu thức có kiểu đơn giản
nh Integer, real, Boolean, String.
Cách viết vào tệp văn bản cũng nh cách viết ra màn hình nhng khác với màn
hình chỉ hạn chế có 80 dòng x 25 cột. Còn tệp văn bản có số dòng, cột không
giới hạn (xem lại Chơng 3 : Thủ tục vào ra dữ liệu)
c.Đọc dữliệu từ tệp văn bản
Chúng ta có thể đọc không những kí tự từ tệp văn bản mà còn có thể đọc các số
nguyên số thực, boolean từ tệp văn bản thông qua các thủ tục
Read(Biến_Tệp, Var1, Var2, VarN); (1)
Readln(Biến_Tệp, Var1, Var2, VarN); (2)
Readln(Biến_Tệp); (3)
Trong đó Var1, Var2, VarN là các biến kiểu Char, Integer, String, Real,
Boolean.
Thủ tục (2) đọc xong sẽ đa cửa sổ tệp sang đầu dòng tiếp theo
Thủ tục (3) không đọc gì cả chỉ đa cửa sổ tệp sang đầu dòng tiếp theo
8. Kiểm tra tệp khi mở
3
Xét đoạn chơng trình sau sẽ kiểm tra xem tệp F có trên đĩa hay không
VAR st:string;
F:TEXT;
BEGIN
Write('Nhập tên tệp : ');readln(st);
assign(f,st);{$I-} reset(f);
if ioresult=0 then write('Tệp ',St,' có trên đĩa')
else write('Tệp ',St,' không có trên đĩa')
END;
9. Tệp không định kiểu
Tệp không định kiểu là một kiểufile đặc biệt. Đó là tệp khi định nghĩa hay khai
báo ra, ta không nói rõ nó chứa gì, không nói rõ bản chất các dữliệu ghi trong
đó. Vì vậy việc chuyển dữliệu từ đĩa vào cấu trúc dữliệu sẽ đợc thực hiện ngay
lập tức. Đó là lí do vì sao tệp không định kiểu đợc dùng rộng rãi trong các ứng
dụng đòi hỏi tốc độ cao.
Cách khai báo
VAR Biến_tệp : FILE;
Việc ghi và đọc dữliệu đối với tệp không định kiểu thờng xuyên dùng đến 2 thủ
tục
BLOCKREAD và BLOCKWRITE
{ Nhập N. Sau đó nhập N số nguyên từ bàn phím Ghi các số đó vào file
'bai1.dat'. Sau đó mở lại file đó đọc N số đó và tính tổng của chúng (file kiểu
byte)}
uses crt;
var
i,a,n:byte;{i,a,n kiểu byte}
f:file of byte;{biến f kiểu tệp (byte)}
tong:integer;{tong kiểu integer}
begin
clrscr;{Xoá màn hình}
assign(f,'bai1.dat');rewrite(f);{Mở file bai1.dat để ghi}
write('N = ');readln(n);{Đọc N}
for i:=1 to n do{Cho i chạy từ 1 đến N}
begin
write('Nhap so thu ',i,' : ');readln(a);{Đọc số thứ i vào a}
write(f,a);{Ghi a vào f}
end;
close(f);{Đóng tệp F}
tong:=0;{Gán tong bằng 0}
assign(f,'bai1.dat');reset(f);{Mở file bai1.dat để đọc}
for i:=1 to n do{Cho i chạy từ 1 đến N}
begin
read(f,a);{Đọc từ f biến a}
inc(tong,a);{Cộng a vào tổng}
end;
writeln('Tong = ',tong);{Xuất tổng}
4
readln;
end.
{ Viết thủ tục taofile(s:string;n:integer) tạo ra n số nguyên ngẫu nhiên từ
1 10000 rồi sau đó ghi và file (kiểu integer)có tên là s
Sau đó thử tạo ra file 'bai21.dat' có 10 phần tử, 'bai22.dat' có 20 phần tử}
uses crt;
var
f:file of integer;{f kiểu tệp integer}
procedure taofile(s:string;n:integer);
var i,a:integer;{Khai báo i,a kiểu integer}
begin
assign(f,s);rewrite(f);{Mởi file s để ghi}
for i:=1 to n do{Cho i chạy từ 1 đến n}
begin
a:=random(10000)+1;{Gán a bằng số ngẫu nhiên từ 1 10000}
write(f,a);{Ghi a vào f}
end;
close(f);{Đóng tệp f}
end;
begin
randomize;
taofile('bai21.dat',10);
taofile('bai22.dat',20);
end.
{ Viết chơng trình tơng tự nh bài tập 2 nhng lần này tạo ra n kí tự ngẫu
nhiên trong khoảng từ 'A' 'Z' và ghi vào tệp 'bai3.dat'. Sau đó mở lại file
đếm xem có bao nhiêu kí tự 'A', bao nhiêu 'B' }
uses crt;
var
dem:array['A' 'Z']of byte;{Mảng dem['A' 'Z'] kiểu byte}
f:file of char;{f kiểu tệp kí tự}
ch:char;{ch kiểu kí tự}
i,n:byte;{i,n kiểu byte}
procedure taofile(s:string;n:integer);
var i:byte;{Khai báo i kiểu byte}
begin
assign(f,s);rewrite(f);{Mở file s để ghi}
for i:=1 to n do{Cho i chạy từ 1 đến N}
begin
ch:=chr(random(26)+65);{Gán ch bằng kí tự ngẫu nhiên từ 'A' 'Z'}
write(f,ch);{Ghi ch vào f}
end;
close(f);{Đóng tệp f}
end;
begin
clrscr;{Xoá màn hình}
5
randomize;
write('N = ');readln(n);{Đọc N}
taofile('bai3.dat',n);
assign(f,'bai3.dat');reset(f);{Mở file bai3.dat để đọc}
for i:=1 to n do{Cho i chạy từ 1 đến N}
begin
read(f,ch);{Đọc kí tự ch từ f}
inc(dem[ch]);{Tăng dem[ch]}
end;
for ch:='A' to 'Z' do{Cho ch chạy từ 'A' 'Z'}
if dem[ch]>0 then{Nếu ch có xuất hiện thì}
writeln('Chu ',ch,' xuat hien ',dem[ch],' lan');{Xuất ch và số lần xuất hiện}
readln;
end.
{ Tạo ra 2 file số nguyên ngẫu nhiên (bài 2) file 1 có m phần tử, file 2 có n
phần tử rồi sau đó ghi vào file bai41.dat, bai42.dat Sau đó mở lại 2 file này.
Đọc hết các phần tử của 2 file vào mảng A. Sắp xếp lại theo thứ tự tăng dần
rồi sau đó ghi vào file bai4.dat}
uses crt;
var
a:array[1 10000]of integer;{Mảng a 10000 phần tử kiểu integer}
f:file of integer;{f kiểu tệp integer}
i,j,tg,m,n:integer;{i,j,tg,m,n kiểu byte}
procedure taofile(s:string;n:integer);
var i,a:integer;{Khai báo i,a kiểu integer}
begin
assign(f,s);rewrite(f);{Mở file s để ghi}
for i:=1 to n do{Cho i chạy từ 1 đến N}
begin
a:=random(10000)+1;{Gán a bằng số ngẫu nhiên từ 1 10000}
write(f,a);{Ghi a vào tệp f}
end;
close(f);{Đóng tệp f}
end;
begin
clrscr;{Xoá màn hình}
randomize;
write('M = ');readln(m);{Đọc M}
write('N = ');readln(n);{Đọc N}
taofile('bai41.dat',m);
taofile('bai42.dat',n);
assign(f,'bai41.dat');reset(f);{Mở file bai41.dat để đọc}
for i:=1 to m do read(f,a[i]);{Đọc m phần tử tử f vào a}
close(f);{Đóng tệp f}
assign(f,'bai42.dat');reset(f);{Mở file bai42.dat để đọc}
for i:=1 to n do read(f,a[m+i]);{Đọc n phần tử tử f vào a}
6
close(f);{Đóng tệp f}
for i:=1 to m+n-1 do{Cho i chạy từ 1 đến m+n-1}
for j:=i+1 to m+n do{Cho j chạy từ i+1 đến m+n}
if a[i]>a[j]then{Nếu a[i]>a[j] thì}
begin
tg:=a[i];a[i]:=a[j];a[j]:=tg;{Đổi chỗ a[i],a[j]}
end;
assign(f,'bai4.dat');rewrite(f);{Mở file bai4.dat để ghi}
for i:=1 to m+n do write(f,a[i]);{Ghi m+n phần tử từ a vào f}
close(f);{Đóng tệp f}
end.
{ Viết chơng trình nhập từ bàn phím liên tục các xâu S. Ghi chúng vào file
'bai5.txt'. Chơng trình kết thúc khi nhập chuỗi S rỗng}
uses crt;
var
s:string;{Xâu S}
f:text;{f kiểu tệp văn bản}
begin
clrscr;
assign(f,'bai5.txt');rewrite(f);{Mở file bai5.txt để ghi}
repeat
readln(s);{Đọc S}
if s<>''then writeln(f,s);{Nếu S không rỗng thì ghi s vào f}
until s='';{Cho đến khi S rỗng}
close(F);{Đóng tệp F}
end.
{ Viết chơng trình nhập từ file 'bai61.txt' là file văn bản. Tạo ra file
'bai62.txt' có nội dung tơng tự nh file 'bai61.txt' nhng đổi tất cả kí tự thờng
trong file bai61.txt thành kí tự hoa
Hớng dẫn
WHILE not EOF(F)DO
BEGIN
Đọc xâu S từ file F
Đổi S thành hoa
Ghi S vào file F1
END}
uses crt;
var
s:string;{Xâu S}
f,f1:text;{F,F1 kiểu tệp văn bản}
i:byte;{i kiểu byte}
begin
assign(f,'bai61.txt');reset(f);{Mở file bai61.txt để đọc (dùng biến F)}
assign(f1,'bai62.txt');rewrite(f1);{Mở file bai62.txt để ghi (dùng biến F1)}
while not eof(f)do{Trong khi cha hết file f thì}
begin
7
readln(f,s);{Đọc xâu S từ F}
for i:=1 to length(s)do s[i]:=upcase(s[i]);{Đổi S thành hoa}
writeln(f1,s);{Ghi xâu S vào F1}
end;
close(F);close(f1);{Đóng f,f1}
end.
{ Viết chơng trình tạo 2 tệp văn bản có tên là bai71.txt bai72.txt. Mỗi tệp có
100 dòng. Mỗi dòng là một số nguyên đợc tạo ngẫu nhiên
Sau đó mở file bai71.txt. Đọc các số trongfile đó và ghép vào cuối file
bai72.txt
Hớng dẫn
Sau khi tạo file xong thì
- Dùng thủ tục APPEND đối với bai72.txt để ghi vào cuôi
- Đọc lần lợt các số từ tệp bai71.txt rồi ghi vào tệp bai72.txt một cách bình th-
ờng}
uses crt;
var
s:string;{Xâu S}
f,f1:text;{F,F1 kiểu tệp văn bản}
i:byte;{i kiểu byte}
procedure taofile(s:string);
var i,a:integer;{Khai báo i,a kiểu integer}
begin
assign(f,s);rewrite(f);{Mở file s để ghi}
for i:=1 to 100 do{Cho i chạy từ 1 đến 100}
begin
a:=random(10000)+1;{Gán a bằng số ngẫu nhiên từ 1 10000}
writeln(f,a);{Ghi a vào f}
end;
close(f);{Đóng tệp f}
end;
begin
taofile('bai71.txt');
taofile('bai72.txt');
assign(f,'bai71.txt');reset(f);{Mở file bai71.txt để đọc (dùng biến F)}
assign(f1,'bai72.txt');append(f1);{Mở file bai72.txt để ghi vào cuối (dùng biến
F1)}
for i:=1 to 100 do{Cho i chạy từ 1 đến 100}
begin
readln(f,s);{Đọc xâu s từ F}
writeln(f1,s);{Ghi xâu S vào F1}
end;
close(f);close(f1);{Đóng tệp f,f1}
end.
{ Viết chơng trình đọc từ bàn phím chuỗi S1 và chuỗi S2. Nếu file có tên S1
tồn tại thì đổi tên S1 thành S2 ngợc lại thông báo file không tồn tại}
8
uses crt;
var
f:file;{f kiểu tệp bất kì}
s1,s2:string;{Xâu S1,S2}
begin
clrscr;{Xoá màn hình}
write('S1 = ');readln(s1);{Đọc S1}
write('S1 = ');readln(s2);{Đọc S2}
assign(f,s1);{$I-}Reset(f);{$I+}
if IOResult <> 0 then write('File ',s1,' khong ton tai'){Nếu IOResult<>0 thì
không tồn tại}
else{Ngợc lại}
begin
Close(F);{Đóng tệp F}
rename(F,s2);{Đổi tên D thành S2}
end;
readln;
end.
{ Nhập S. Viết chơng trình hiển thị file văn bản có tên S lên màn hình. Nếu
văn bản đó dài thì hiển thị từng trang rồi sau đó đợi cho ngời dùng bấm
phím Enter thì hiển thị tiêp
Hớng dẫn
i:=0;
WHILE not EOF(F)DO
BEGIN
Đọc và xuất xâu S
IF i=23 THEN readln;
END;}
uses crt;
var f:text;{f kiểu tệp văn bản}
i:byte;{i kiểu byte}
s:string;{Xâu S}
begin
clrscr;{Xoá màn hình}
write('S = ');readln(s);{Đọc S}
assign(f,s);reset(f);{Mở s để đọc}
i:=0;{Gán i=0}
while not eof(f)do{Trong khi cha hết tệp F thì}
begin
readln(f,s);{Đọc S}
writeln(s);{Xuất S}
inc(i);{Tăng i}
if i=23 then begin i:=0;readln;end;{Nếu i=23 thì gán i=0 và dừng lại đợi}
end;
close(f);{Đóng tệp F}
end.
9
{ Viết chơng trình mã hoá một file văn bản bằng cách : Đổi các kí tự trong
file văn bản đó thành kí tự có mã = (255-mã_kí_tự_cũ) (đổi tất cả các kí tự
kể cả kí tự CR,LF )
Hớng dẫn
Ta mở file văn bản đó dới dạng file kí tự rồi lần lợt đọc từng kí tự đổi mã rồi ghi
vào file mới
Giải mã thì chỉ cần chạy lại chơng trình mã hoá đối với file đã mã hoá}
uses crt;
var
f,f1:file of char;{f,f1 kiểu tệp kí tự}
ch:char;{ch kiểu kí tự}
s:string;{Xâu S}
begin
clrscr;{Xoá màn hình}
write('S = ');readln(s);{Đọc S}
assign(f,s);reset(f);{Mở file S để đọc (dùng biến F)}
assign(f1,'mahoa.dat');rewrite(f1);{Mở file mahoa.dat để ghi (dùng biến F1)}
while not eof(f)do{Trong khi file f cha hết thì}
begin
read(f,ch);{Đọc kí tự ch từ f}
ch:=chr(255-ord(ch));{Mã hoá ch}
write(f1,ch);{Ghi ch vào f1}
end;
close(f);close(f1);{Đóng tệp f,f1}
end.
10
. tiếp
VAR
Biến_tệp : FILE OF Kiểu_ phần_tử;
VD :
TYPE
FileInteger = FILE OF integer;
FileReal = FILE OF real;
FileBoolean = FILE OF Boolean;
Nhan_su. END;
VAR
F1,F2 : FileInteger;
F3 : FileReal;
FNS : FILE OF Nhan_su;
F5 : FILE OF Char;
3.Mở tệp mới để cất dữ liệu
a. Mở tệp để ghi
Pascal dùng 2 thủ