1. Lập trình hướng đối tượng với C++
Tài liệu tham khảo:
FILE TRONG C++
Luồng
Trước khi ta có thể làm việc với file trong C++, ta cần phải làm quen với khái niệm về
luồng.
Ta có thể hiểu luồng là một kênh (channel) hay một ống (pipe) mà thông qua đó, dữ liệu
có thể được trao đổi/chuyển (flow) từ chương trình tới một thiết bị nhập xuất.
Dữ liệu có thể được gởi ra từ chương trình tới các thiết bị xuất như màn hình, máy in hay
file,... qua luồng xuất (output stream) hoặc chương trình chúng ta có thể nhận dữ liệu từ
các thiết bị nhập chuẩn như bàn phím, file,... qua luồng nhập (input stream).
Ví dụ:
- Chúng ta đã làm quen với một luồng nhập cin. Đây là luồng nhập chuẩn được nối
kết (connect) với bàn phím, cho phép chúng ta nhận dữ liệu từ bàn phím.
- Chúng ta cũng đã làm quen với luồng xuất cout. Đây là luồng xuất chuẩn được
nối kết với màn hình, cho phép ta gởi dữ liệu ra màn hình
Khi một luồng dã được nối kết với một thiết bị nào đó (hoặc tập tin) thì ta có thể gởi dữ
liệu tới thiết bị hoặc nhận dữ liệu từ thiết bị đó thông qua luồng.
Tập tin thư viện cho phép ta làm việc với với luồng file (file stream) là fstream. Vì vậy,
để làm việc được với file trong C++, chúng ta phải include thư viện này trong chương
trình:
#include <fstream>
Tạo luồng (Creating Stream)
Trước khi chúng ta có thể dùng các luồng nhập/xuất file (file input/output stream), chúng
ta phải tạo ra chúng. Cú pháp:
ifstream in_stream; //tạo luồng file nhập
ofstream out_stream; //tạo luồng file xuất
Luồng nhập ifstream dùng để đọc dữ liệu từ file ra chương trình của chúng ta
Luồng xuất ofstream dùng để ghi dữ liệu từ chương trình ra file.
Nối kết và ngắt nối kết giữa luồng với file
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
1
2. Lập trình hướng đối tượng với C++
Sau khi đã tạo ra các luồng nhập/xuất, chúng ta có thể dùng phương thức "open(...)".
để nối kết luồng với file cần mở hay tạo.
Ví dụ: Để nối kết luồng ifstream (luồng file nhập) "in_stream" đã mở trong ví dụ trên
tới file "test.txt", ta dùng câu lệnh như sau:
in_stream.open("test.txt");
Sau khi nối kết, luồng này sẽ ở vị trí đầu file "test.txt".
Để nối kết luồng xuất ofstream "out_stream" đến file “test.txt”, chúng ta dùng câu lệnh
tương tự:
out_stream.open("test.txt");
Với lệnh nối kết luồng xuất với file như thế này, nếu file đã có sẵn trên đĩa thì nội dung
cũ của file sẽ bị xóa, sẵn sàng cho việc nhập mới.
Để ngắt nối kết một luồng ra khỏi file, ta dùng phương thức close của luồng đó.
Ví dụ: để ngắt nối kết giữa luồng nhập ifstream "in_stream" và file, ta dùng lệnh sau:
in_stream.close();
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
2
3. Lập trình hướng đối tượng với C++
Kiểm tra kết quả của các câu lệnh truy xuất file
Những thao tác trên file như mở file, đóng file, thường là nguồn gốc gây ra lỗi. Do đó, ta
phải kiểm tra lỗi của những câu lệnh này mỗi khi thực hiện chúng để có những sửa lỗi
thích hợp. Để kiểm tra lỗi, ta dùng hàm "fail()".
Ví dụ: in_stream.fail();
Hàm này trả về giá trị true (khác 0) nếu lệnh truy xuất file trước đó thành công, false (0)
nếu không thành công.
Ví dụ: câu lệnh in_stream.fail() sẽ trả về giá trị 0 nếu một thao tác trên "in_stream"
không thành công (có thể là do chúng ta mở file nhưng file đó không tồn tại).
Nếu một lỗi nào đó xảy ra, "in_stream" sẽ ở trong trạng thái lỗi và chúng ta không thể
dùng nó để thao tác trên file. Chúng ta phải sửa lỗi trước khi thực thi tiếp các thao tác
tiếp theo hoặc thoát khỏi chương trình, dùng lệnh "exit(1)" trong thư viện hàm
"cstdlib". Ví dụ:
#include <iostream.h>
#include <fstream.h>
#include <cstdlib.h>
int main()
{
ifstream in_stream;
in_stream.open("Lecture_4");
if (in_stream.fail())
{
cout << "Sorry, the file couldn't be opened!n";
exit(1);
}
...
Đọc/ghi ký tự (Charater input and output):
Đọc ký tự dùng "get(...)"
Sau khi gắn luồng nhập istream vào một file (mở file), chúng ta có thể đọc một ký tự từ
file dùng hàm thành viên "get(...)". Hàm này nhận vào một tham số kiểu "char".
Ví dụ: đối với luồng in_stream đã mở ở trên, ta có thể đọc một ký tự vào biến ch bằng
lệnh sau (xem hình minh họa):
in_stream.get(ch);
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
3
4. Lập trình hướng đối tượng với C++
Lệnh này sẽ thực hiện 2 thao tác: biến "ch" được gán cho ký tự "'4'", và luồng nhập
"in_stream" được dời vị trí tới ký tự kế tiếp trong file, sẵn sàng cho việc đọc ký tự kế
tiếp
Ghi ký tự dùng "put(...)"
Chúng ta cũng có thể ghi một ký tự ra file đã mở thông qua luồng xuất ostream bằng hàm
"put(...)". Hàm này cũng nhận vào 1 tham số kiểu ký tự, là ký tự mà ta muốn ghi ra
file.
Ví dụ: out_stream.put('4');
Cũng tương tự như hàm get(...), sau khi thực hiện ghi ra file, luồng sẽ tự dời đến ký
kế tiếp (thường là vị trí end-of-file).
Kiểm tra cuối file (end of file):
Để kiểm tra xem chúng ta đã truy xuất đến cuối file hay chưa, chúng ta dùng hàm
"eof()" của luồng nhập ifstreams.
Hình sau sẽ minh họa việc đọc dữ liệu từ file
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
4
5. Lập trình hướng đối tượng với C++
Nếu luồng nhập istream đã đến vị trí cuối file mà ta dùng hàm “get(...)” để đọc ký tự
vào một biến thì biến đó sẽ mang một giá trị không hợp lệ.
in_stream.get(ch);
Kết quả của in_stream.eof() sẽ trả về giá trị true (khác 0).
Ví dụ: chương trình sau đây sẽ mở file ‘test.txt’ và in nội dung của nó ra màn hình, đồng
thời tạo file ‘copy_of_test.txt’ và copy nội dung của file ‘test.txt’ sang.
#include <iostream.h>
#include <fstream.h>
int main()
{
char character;
ifstream in_stream;
ofstream out_stream;
in_stream.open("test.txt");
out_stream.open("Copy_of_test.txt");
in_stream.get(character);
while (!in_stream.eof())
{
cout << character; //in ky tu ra man hinh
out_stream.put(character);
in_stream.get(character);
}
out_stream.close();
in_stream.close();
return 0;
}
Đọc/ghi file dùng toán tử ">>" và “<<”
Ở phần trên, chúng ta đã xem qua cách đọc một ký tự từ file hoặc viết một ký tự ra file.
Luồng xuất ofstreams và luồng nhập ifstreams chỉ làm việc với những ký tự, vì vậy
những kiểu dữ liệu khác như "int", "double",... sẽ được chuyển qua các ký tự trước khi
chúng được viết vào file và sẽ được chuyển ngược lại khi chúng được đọc ra.
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
5
6. Lập trình hướng đối tượng với C++
Tuy nhiên, các toán tử ">>" và "<<" mà chúng ta đã gặp khi học về cách xuất dữ liệu ra
màn hình hoặc nhập dữ liệu từ bàn phím, sẽ thực hiện sự chuyển đổi này một cách tự
động. Ví dụ, nếu chúng ta có một luồng đang ở trạng thái như sau:
khi chúng ta thực thi câu lệnh
out_stream << 437 << ' ';
thì kết quả là chúng ta có trạng thái như sau:
* Chú ý: các số integer phải cách nhau khoảng trắng.
khi biến n có kiểu là "int", thực thi câu lệnh
in_stream >> n;
ta có kết quả như sau:
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
6
7. Lập trình hướng đối tượng với C++
Chú ý là toán tử ">>" sẽ bỏ qua các ký tự trắng "' '", ngay cả khi chúng ta đọc vào
những ký tự.
Ví dụ: chương trình sau đây sẽ tạo 1 file c1o tên là ‘Integers’ và ghi vào file các số
nguyên 51, 52, 53, 54 and 55, sau đó sẽ đọc file này bằng các kiểu dữ liệu khác nhau.
#include <iostream.h>
#include <fstream.h>
int main()
{
char character;
int number = 51;
int count = 0;
ofstream out_stream;
ifstream in_stream1; /* Stream for counting integers*/
ifstream in_stream2; /* Stream for counting chars */
/* Create the file */
out_stream.open("Integers");
for (count = 1 ; count <= 5 ; count++)
out_stream << number++ << ' ';
out_stream.close();
/* Count the integers in the file */
in_stream1.open("Integers");
count = 0;
in_stream1 >> number;
while (!in_stream1.eof())
{
count++;
in_stream1 >> number;
}
in_stream1.close();
cout << "There’re " << count << " integers in the file";
/* Count the non-blank characters */
in_stream2.open("Integers");
count = 0;
in_stream2 >> character;
while (!in_stream2.eof())
{
count++;
in_stream2 >> character;
}
in_stream2.close();
cout << "represented using " << count << " chars.n";
return 0;
}
Đọc chuỗi từ file:
Chúng ta có thể đoc một chuỗi (kết thúc bằng ký tự kết thúc chuỗi ‘n’) từ file bằng hàm
thành viên “getline(...)” của luồng nhập istream. Cú pháp của hàm này tương
tự như trường hợp nhập từ bàn phím.
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
7
8. Lập trình hướng đối tượng với C++
Ví dụ: chương trình “docchuoi.cpp” sau sẽ in nội dung của chính nó ra màn hình, kèm
theo số thứ tự dòng trước mỗi dòng.
#include <iostream.h>
#include <fstream.h>
int main()
{
char string[200];
int count = 0;
ifstream in_stream; /*stream for getting line */
/* Get the content of the file */
in_stream1.open("docchuoi");
count = 0;
in_stream.getline(string, 200);
while (!in_stream.eof())
{
count++;
cout < count << “: “ << string < endl;
in_stream1.getline(string, 200);
}
in_stream.close();
cout << "There’re " << count << " lines in the file";
return 0;
}
Đọc/ghi đối tượng (objects):
Xuất đối tượng:
Muốn xuất đối tượng vào file, ta phải mở file ở chế độ binary:
ofstream out_stream;
out_stream.open(<filename>, ios:binary);
Khi viết đối tượng vào file, ta phải ép kiểu đối tượng về kiểu char*:
Hocsinh hs(....);
out_stream << (char*)&hs;
Đọc đối tượng:
Tương tự xuất đối tượng, khi đọc đối tượng từ file vào một biến, ta phải ép kiểu
đối tượng về kiểu char*:
ifstream in_stream;
in_stream.open(<filename>, ios:binary);
Hocsinh hs(....);
in_stream >> (char*)&hs;
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
8
9. Lập trình hướng đối tượng với C++
Ví dụ: chương trình sau minh họa cách sử dụng đối tượng với file
#include <iostream.h>
#include <fstream.h>
#include <string.h>
class Hocsinh {
char hoten[80];
char lop[10];
float dtb;
public:
Hocsinh();
Hocsinh(char* ht, char* l, float d);
void hien();
};
Hocsinh::Hocsinh() {
strcpy(hoten, “”);
strcpy(lop, “”);
dtb = 0.0
}
Hocsinh::Hocsinh(char* ht, char* l, float d) {
strcpy(hoten, ht);
strcpy(lop, l);
dtb = d;
}
void hien() {
cout << “Ho ten: ” << hoten;
cout << “ - Lop: ” << lop;
cout << endl << “Trung binh: ” << dtb;
}
int main()
{
Hocsinh hs1(“Phan Thuong Cang”, “DI935601”, 8.5);
Hocsinh hs2;
ofstream out_stream; /*stream để xuất đối tượng*/
ifstream in_stream; /*stream để đọc đối tượng*/
/* Get the content of the file */
out_stream1.open("hocsinh.txt", ios:binary);
out_stream << (char*) &hs1;
out_stream.close();
in_stream.open(“hocsinh.txt”, ios::binary);
in_stream >> (char*) &hs2;
in_stream.close();
return 0;
}
/home/vanlong/Backup_Windows/ContentDiskD/BaiGiang/C++/An/C++/TL Tham
khao/FILE trong C++.doc
9