Thao tác cơ bản với tập tin:
Tạo đối tượng gắn với tập tin:
Mỗi lớp ifstream và ofstream cung cấp 4 phương thức để tạo file (tập tin). Có 2 cách hay dùng:
- Cách 1:
<Lớp> đối_tượng;
đốitượng.open(tên_file, chếđộ);
Lớp là một trong hai lớp ifstream và ofstream. Đối tượng là tên do người dùng tự đặt. Chế độ là cách thức làm việc với file. Cách này cho phép tạo trước một đối tượng chưa gắn với file cụ thể nào. Sau đó dùng tiếp phương thức open để đồng thời mở file và gắn với đối tượng vừa tạo
Ví dụ:
ifstream inf;
// tạo đối tượng có tên inf để đọc
ofstream ouf;
// tạo đối tượng có tên ouf để ghi
inf.open(“Baitap”);
// mở file Baitap và gắn với inf
- Cách 2:
<Lớp> đốitượng(tên_file, chếđộ);
Cách này cho phép đồng thởi mở file cụ thể và gắn file với tên đối tượng trong câu lệnh.
Ví dụ:
ifstream inf(“Baitap”); // mở file Baitap và gắn với đối tượng inf để đọc
Sau khi mở file và gắn với đối tượng f, mọi thao tác trên f cũng chính là làm việc với file Baitap.
Trong các câu lệnh trên có các chế độ để qui định cách thức làm việc của file. Các chế độ này gồm có:
- ios::binary : quan niệm file theo kiểu nhị phân. Mặc định là kiểu văn bản
- ios::in : file để đọc (mặc định định với đối tượng trong ifstream).
- ios::out : file để ghi (mặc định với đối tượng trong ofstream), nếu file đã có trên đĩa thì nội dung của nó sẽ bị ghi đè (bị xóa).
- ios::app : bổ sung vào cuối file.
- ios::trunc : xóa nội dung file đã có.
- ios::ate : chuyển con trỏ đến cuối file
- ios::nocreate : không làm gì nếu file chưa có
- ios::replace : không làm gì nếu file đã có
Có thể chỉ định cùng lúc nhiều chế độ bằng cách ghi chúng liên tiếp nhau với toán tử hợp bit |. Ví dụ để mở file bài tập như một file nhị phân và ghi tiếp theo vào cuối file ta dùng câu lệnh:
ofstream f(“Baitap”, ios::binary | ios::app);
Đóng file và giải phóng đối tượng:
Sử dụng phương thức close như sau:
đối_tượng.close();
Sau khi đóng file (và giải phóng mối liên kết giữa đối tượng và file) có thể dùng đối tượng để gắn và làm việc với file khác bằng phương thức open như trên.
Ví dụ: Đọc một dãy số từ bàn phím và ghi lên file. File được xem như file văn bản (ngầm định), các số được ghi cách nhau 1 dấu cách.
include <iostream.h>
include <fstream.h>
include <conio.h>
void main()
{
ofstream f; // khai báo (tạo) đối tượng f
int x;
f.open("DAYSO"); // mở file DAYSO và gắn với f
for (int i = 1; i<=10; i++) {
cin >> x;
f << x << ' ';
}
f.close();
}
Kiểm tra sự tồn tại của file, kiểm tra hết file:
Việc mở một file chưa có để đọc sẽ gây nên lỗi và làm dừng chương trình. Khi xảy ra lỗi mở file, giá trị trả lại của phương thức bad là một số khác 0. Do vậy có thể sử dụng phương thức này để kiểm tra một file đã có trên đĩa hay chưa. Ví dụ:
ifstream f("Bai tap");
if (f.bad()) {
cout << "file Baitap chưa có";
exit(1);
}
Khi đọc hoặc ghi, con trỏ file sẽ chuyển dần về cuối file. Khi con trỏ ở cuối file, phương thức eof() sẽ trả lại giá trị khác không. Do đó có thể sử dụng phương thức này để kiểm tra đã hết file hay chưa.
Chương trình sau cho phép tính độ dài của file Baitap. File cần được mở theo kiểu nhị phân.
include <iostream.h>
include <fstream.h>
include <stdlib.h>
include <conio.h>
void main()
{
clrscr();
long dodai = 0;
char ch;
ifstream f("Baitap", ios::in | ios::binary) ;
if (f.bad()) {
cout << "File Baitap không có";
exit(1);
}
while (!f.eof()) {
f.get(ch));
dodai++;
}
cout << "Độ dài của file = " << dodai;
getch();
}
Đọc ghi đồng thời trên file:
Để đọc ghi đồng thời, file phải được gắn với đối tượng của lớp fstream là lớp thừa kế của 2 lớp ifstream và ofstream. Khi đó chế độ phải được bao gồm chỉ định ios::in | ios::out. Ví dụ:
fstream f("Data", ios::in | ios::out) ;
hoặc
fstream f ;
f.open("Data", ios::in | ios::out) ;
Di chuyển con trỏ file:
Các phương thức sau cho phép làm việc trên đối tượng của dòng xuất (ofstream).
- đối_tượng.seekp(n) ; Di chuyển con trỏ đến byte thứ n (các byte được tính từ 0)
- đối_tượng.seekp(n, vị trí xuất phát) ; Di chuyển đi n byte (có thể âm hoặc dương) từ vị trí xuất phát. Vị trí xuất phát gồm:
- ios::beg : từ đầu file
- ios::end : từ cuối file
- ios::cur : từ vị trí hiện tại của con trỏ.
- đối_tượng.tellp(n) ; Cho biết vị trí hiện tại của con trỏ.
Để làm việc với dòng nhập tên các phương thức trên được thay tương ứng bởi các tên : seekg và tellg. Đối với các dòng nhập lẫn xuất có thể sử dụng được cả 6 phương thức trên.
Ví dụ : Chương trình nhập và in danh sách sinh viên trên ghi/đọc đồng thời.
include <iostream.h>
include <iomanip.h>
include <fstream.h>
include <stdlib.h>
include <stdio.h>
include <conio.h>
include <ctype.h>
void main() {
int stt ;
char *hoten, *fname, traloi;
int tuoi;
float diem;
fstream f;
cout << "Nhập tên file: ";
cin >> fname;
f.open(fname, ios::in | ios::out | ios::noreplace) ;
if (f.bad()) {
cout << "Tệp đã có. Ghi đè (C/K)?" ;
cin.get(traloi) ;
if (toupper(traloi) == 'C') {
f.close() ;
f.open(fname, ios::in | ios::out | ios::trunc) ;
} else exit(1);
}
stt = 0;
f << setprecision(1) << setiosflags(ios::showpoint) ;
// nhập danh sách
while (1) {
stt++;
cout << "\nNhập sinh viên thứ " << stt ;
cout << "\nHọ tên: "; cin.ignore() ;
cin.getline(hoten, 25);
if (hoten[0] = 0) break;
cout << "\nTuổi: "; cin >> tuoi;
cout << "\nĐiểm: "; cin >> diem;
f << setw(24) << hoten << endl;
f << setw(4) << tuoi << set(8) << diem ;
}
// in danh sách
f.seekg(0) ; // quay về đầu danh sách
stt = 0;
clrscr();
cout << "Danh sách sinh viên đã nhập\n" ;
cout << setprecision(1) << setiosflags(ios::showpoint) ;
while (1) {
f.getline(hoten,25);
if (f.eof()) break;
stt++;
f >> tuoi >> diem;
f.ignore();
cout << "\nSinh viên thứ " << stt ;
cout << "\nHọ tên: " << hoten;
cout << "\nTuổi: " << setw(4) << tuoi;
cout << "\nĐiểm: " << setw(8) << diem;
}
f.close();
getch();
}