Open file thư viện cstdio:
FILE* fopen(const char *file, const char *mode); int fclose(FILE *file);
Ghi tới một file trong C
Dưới đây là hàm đơn giản nhất để thực hiện việc ghi các ký tự riêng tới một luồng:
int fputc( int c, FILE *fp );
Đọc file trong C
Dưới đây là hàm đơn giản nhất để đọc một ký tự riêng rẽ từ file:
int fgetc( FILE * fp );
fputs:
int fputs(const char *str, FILE *f);
Hàm fputs ghi một C-Style string vào file được trỏ đến bởi con trỏ f cho đến khi gặp kí tự '\0'.
fprintf:
int fprintf(FILE *f, const char *format, ...);
Hàm fprintf tương tự hàm printf trong ngôn ngữ C. Tuy nhiên, hàm printf được mặc định liên kết với đối tượng FILE có tên là stdout nên sử dụng hàm printf sẽ ghi nội dung ra màn hình.
Hàm printf tương đương với cách sử dụng fprintf(stdout, format, ...).
Và dưới đây là một số hàm được định nghĩa sẵn trong thư viện cstdio hỗ trợ chúng ta đọc dữ liệu văn bản từ file.
- fgetc: int fgetc(FILE *f); Hàm fgetc đọc ra một kí tự trong file, internal file position indicator sẽ chuyển đến kí tự tiếp theo. Giá trị trả về là mã ASCII của kí tự đã đọc được.
char *fgets( char *buf, int n, FILE *fp );
Hàm fgets() đọc n-1 ký tự từ một luồng vào tham chiếu bởi fp. Nó copy chuỗi đọc đến bộ đệm buf, gán ký tự null vào kết thúc chuỗi.
TRONG C++:
Trong C++ thì ta có 3 loại File stream cơ bản sau :
ifstream : Dùng cho file nhập vào. Loại này chỉ có thể được dùng để đọc dữ liệu vào file vào bộ nhớ mà thôi.
ofstream : Dùng cho file xuất ra. Loại này thì có thể dùng để tạo ra files và chép dữ liệu vào chúng.
fstream : Đây là kênh file.(File stream). Loại này thì có thể vừa tạo file, vừa ghi dữ liệu vào file và đọc dữ dữ liệu từ file vào luôn.
ios :: in Mở một tệp tin để đọc
ios :: out Mở một tệp tin có sẵn để ghi
ios :: app Mở một tệp tin có sẵn để thêm dữ liệu vào cuối tệp.
ios :: ate Mở tệp tin và đặt con trỏ tệp tin vào cuối tệp.
ios :: trunc Nếu tệp tin đã có sẵn thì dữ liệu của nó sẽ bị mất.
ios :: nocreate Mở một tệp tin, tệp tin này bắt buộc phải tồn tại
ios :: noreplace Chỉ mở têp tin khi tệp tin chưa tồn tại.
ios :: binary Mở một tệp tin ở chế độ nhị phân
ios :: text Mở một tệp tin ở chế độ văn bản.
TRONG C++:
Trong C++ thì ta có 3 loại File stream cơ bản sau :
ifstream : Dùng cho file nhập vào. Loại này chỉ có thể được dùng để đọc dữ liệu vào file vào bộ nhớ mà thôi.
ofstream : Dùng cho file xuất ra. Loại này thì có thể dùng để tạo ra files và chép dữ liệu vào chúng.
fstream : Đây là kênh file.(File stream). Loại này thì có thể vừa tạo file, vừa ghi dữ liệu vào file và đọc dữ dữ liệu từ file vào luôn.
1.Cách sử dụng fstream
1.1.Đối với file văn bản (File dạng *.txt)
Để định nghĩa 1 đối tượng file ta dùng cú pháp sau : fstream dataFile
Ở đây dataFile chỉ là tên biến do người dùng đặt ra.
Để mở 1 file ta dùng cú pháp sau :
Để mở 1 file ta dùng cú pháp sau :
fstream <Tên biến tệp> (<Tên tệp>, <chế độ mở tệp>);
Hoặc:
Hoặc:
fstream <Tên biến tệp>;
<Tên biến tệp>.open(<Tên tệp>, <chế độ mở tệp>);
<Tên biến tệp>.open(<Tên tệp>, <chế độ mở tệp>);
Ví dụ : fstream dataFile;
dataFile.open("info.txt", ios::out); // hoặc fstream fread ("E: \\data.txt", ios :: in);
Trong đó :
- đối_số_1là 1 chuỗi tên chứa tên file hoặc đường dẫn dẫn đến file
- đối_số_2 là 1 flag của file và cái này cho ta biết chế độ nào mà chúng ta dùng để mở file.
Ở ví dụ trên thì tên file là info.txt còn flag file ở đây là ios::out. Điều này, cho C++ biết chúng ta mở file ở chế độ xuất ra. Chế độ xuất ra cho phép dữ liệu có thể được ghi vào file.
Trường hợp, mở file ở chế độ nhập vào, tức là cho phép dữ liệu được đọc vào từ file.
datafile.open("info.txt", ios::in);
datafile.open("info.txt", ios::in);
Các chế độ mở têp tin <FILE>
ios :: in Mở một tệp tin để đọc
ios :: out Mở một tệp tin có sẵn để ghi
ios :: app Mở một tệp tin có sẵn để thêm dữ liệu vào cuối tệp.
ios :: ate Mở tệp tin và đặt con trỏ tệp tin vào cuối tệp.
ios :: trunc Nếu tệp tin đã có sẵn thì dữ liệu của nó sẽ bị mất.
ios :: nocreate Mở một tệp tin, tệp tin này bắt buộc phải tồn tại
ios :: noreplace Chỉ mở têp tin khi tệp tin chưa tồn tại.
ios :: binary Mở một tệp tin ở chế độ nhị phân
ios :: text Mở một tệp tin ở chế độ văn bản.
Lưu ý:Bạn có thể mở tệp tin đồng thời 1 lúc ở nhiều chế độ.
1.1.1.Các phép xử lý vào/ ra trên file
a.Ghi tệp văn bản bằng:"<<"
Các bước ghi dữ liệu vào tệp tin như sau:
- Mở file chỉ để đọc:
ofstream <Tên biến file> (<Tên file>, ios :: out);
Hoặc:
ofstream <Tên biến file> (<Tên file>); // Mặc định c++ sẽ tự thêm ios :: out
Hoặc:
ofstream <Tên biến file> (<Tên file>); // Mặc định c++ sẽ tự thêm ios :: out
- Ghi dữ liễu vào file thao tác: "<<"
<Tên biến file> << <Dữ liệu cần ghi>;
- Đóng file
<Tên biến file>.close();
b. Đọc tệp văn bản bằng: ">>"
Các bước ghi dữ liệu vào file như:
- Mở file chỉ để đọc:
ofstream <Tên biến file> (<Tên file>, ios :: in);
Hoặc:
ofstream <Tên biến file> (<Tên file>); // Mặc định c++ sẽ tự thêm ios :: in
Hoặc:
ofstream <Tên biến file> (<Tên file>); // Mặc định c++ sẽ tự thêm ios :: in
- Đọc dữ liễu vào file thao tác: "<<"
<Tên biến file> << <Dữ liệu cần đọc>;
- Đóng tệp tin
<Tên biến file>.close();
Ví dụ 1:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream dataFile;
cout << "Thuc hien mo File...\n";
dataFile.open("demofile.txt", ios::out); // Mở file để ghi vào
cout << "Du lieu duoc ghi xuong file.\n";
dataFile << "Mai Anh\n"; // Ghi dòng thứ 1
dataFile << "Thuan Binh\n"; // Ghi dòng thứ 2
dataFile << "An Dong \n"; // Ghi dòng thứ 3
dataFile.close(); // Đóng file
cout << "Xong.\n";
return 0;
}
Output File
Mai Anh
#include <fstream>
using namespace std;
int main()
{
fstream dataFile;
cout << "Thuc hien mo File...\n";
dataFile.open("demofile.txt", ios::out); // Mở file để ghi vào
cout << "Du lieu duoc ghi xuong file.\n";
dataFile << "Mai Anh\n"; // Ghi dòng thứ 1
dataFile << "Thuan Binh\n"; // Ghi dòng thứ 2
dataFile << "An Dong \n"; // Ghi dòng thứ 3
dataFile.close(); // Đóng file
cout << "Xong.\n";
return 0;
}
Output File
Mai Anh
Thuan Binh
An Dong
Quá trình đó thực sự như sau :
Mai Anh\nThuan Binh\nAn Dong\n<EOF>.
Khi file lại được mở ra thì dữ liệu mới lại được gắn vào chỗ end-of-file đó.
Ví dụ 2: Định dạng file xuất ra
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
fstream dataFile;
double num = 17.816392;
dataFile.open("numfile.txt", ios::out);
dataFile << fixed; // Định dạng fixed-point
dataFile << num << endl; //Xuất ra num
dataFile << setprecision(4); // Định dạng 4 phần thập phân sau dấu .
dataFile << num << endl; //Xuất ra num
dataFile << setprecision(3); // Định dạng 3 phần thập phân sau dấu .
dataFile << num << endl; // Xuất ra num
dataFile << setprecision(2); // 2 phần
dataFile << num << endl; // xuất ra
dataFile << setprecision(1); // 1 phần
dataFile << num << endl; // xuất ra
dataFile.close(); // Đóng file
return 0;
}
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
fstream dataFile;
double num = 17.816392;
dataFile.open("numfile.txt", ios::out);
dataFile << fixed; // Định dạng fixed-point
dataFile << num << endl; //Xuất ra num
dataFile << setprecision(4); // Định dạng 4 phần thập phân sau dấu .
dataFile << num << endl; //Xuất ra num
dataFile << setprecision(3); // Định dạng 3 phần thập phân sau dấu .
dataFile << num << endl; // Xuất ra num
dataFile << setprecision(2); // 2 phần
dataFile << num << endl; // xuất ra
dataFile << setprecision(1); // 1 phần
dataFile << num << endl; // xuất ra
dataFile.close(); // Đóng file
return 0;
}
Output
17.816392
17.8164
17.816
17.82
17.8
17.8164
17.816
17.82
17.8
1.1.2.Kiểm tra sự tồn tại của File trước khi mở hoặc mở file không được
Đôi khi chúng ta sẽ cần quyết định xem file có tồn tại trước khi chúng ta mở nó ra hay không và sau đây là 1 ví dụ:
fstream dataFile;
dataFile.open("input.txt", ios::in);
if(dataFile.fail())
{
//Nếu file không tồn tại, thì tạo ra 1 file mới
dataFile.open("input.txt", ios::out);
//...
}
else
{
dataFile.close();
}
fstream dataFile;
dataFile.open("input.txt", ios::in);
if(dataFile.fail())
{
//Nếu file không tồn tại, thì tạo ra 1 file mới
dataFile.open("input.txt", ios::out);
//...
}
else
{
dataFile.close();
}
2.1. Đối với file nhị phân
2.2.1.Định nghĩa :
File nhị phân là file chứa nội dung không nhất thiết phải là ASCII text.
Xét ví dụ sau :
ofstream file("num.dat");
short x = 1297;
file << x;
short x = 1297;
file << x;
Dòng lệnh cuối cùng của ví dụ trên sẽ ghi nội dung của x vào file. Và chúng được lưu vào ở dạng kí tự '1', '2', '9', '7'.
Thực sự là con số 1297 không hề được lưu trong bộ nhớ. Nó đã được định dạng thành 1 số nhị phân, và chiếm 2 byte trong bộ nhớ máy tính.
Vì x kiểu short nó sẽ được lưu như sau :
00000101 | 00010001
Và đây chính là dữ liệu nguyên thuỷ được lưu trong bộ nhớ. Để làm được như vậy chúng ta sẽ có cú pháp như sau :
Thực sự là con số 1297 không hề được lưu trong bộ nhớ. Nó đã được định dạng thành 1 số nhị phân, và chiếm 2 byte trong bộ nhớ máy tính.
Vì x kiểu short nó sẽ được lưu như sau :
00000101 | 00010001
Và đây chính là dữ liệu nguyên thuỷ được lưu trong bộ nhớ. Để làm được như vậy chúng ta sẽ có cú pháp như sau :
file.open("stuff.dat", ios::out | ios::binary);
2.2.2.Vào/ ra trên file nhị phân
Vào ra tệp tin nhị phân bằng: read và write
a.Write
-Hàm write dùng để ghi 1 file stream ở định dạng nhị nhận. Dạng tổng quát của hàm write như sau :
-Hàm write dùng để ghi 1 file stream ở định dạng nhị nhận. Dạng tổng quát của hàm write như sau :
fileObject.write(address, size);
Lưu ý :
-fileObject là tên của đối tượng file stream.
-address là địa chỉ đầu tiên của 1 vùng nhớ được ghi vào file. Đối số này có thể là địa chỉ của 1 kí tự hoặc là con trỏ tới kiểu char.
-size là số lượng byte của vùng nhớ mà nó được write. Đối số này bắt buộc phải là kiểu integer( số nguyên dương )
Ví dụ :
-fileObject là tên của đối tượng file stream.
-address là địa chỉ đầu tiên của 1 vùng nhớ được ghi vào file. Đối số này có thể là địa chỉ của 1 kí tự hoặc là con trỏ tới kiểu char.
-size là số lượng byte của vùng nhớ mà nó được write. Đối số này bắt buộc phải là kiểu integer( số nguyên dương )
Ví dụ :
char letter = 'A';
file.write(&letter, sizeof(letter));
file.write(&letter, sizeof(letter));
-Đối thứ nhất ở đây là địa chỉ của biến letter. Và đối này sẽ nói cho hàm write biết rằng dữ liệu được ghi vào file ở đâu trong vùng nhớ.
-Đối thứ 2 sẽ là kíck thước của biến letter, và đối này sẽ nói cho hàm write biết số lượng byte của dữ liệu sẽ ghi vào file. Bởi vì dữ sẽ được lưu khác nhau trên tuỳ hệ thống khác nhau, nên cách tốt nhất là chúng ta dùng toán tử sizeof để quyết định số bytes được ghi. Và sau khi hàm này được thực hiện, nội dung của biến letter sẽ được khi vào file nhị phân của đối tượng "file"đó.
Chúng ta xem tiếp 1 ví dụ khác
-Đối thứ 2 sẽ là kíck thước của biến letter, và đối này sẽ nói cho hàm write biết số lượng byte của dữ liệu sẽ ghi vào file. Bởi vì dữ sẽ được lưu khác nhau trên tuỳ hệ thống khác nhau, nên cách tốt nhất là chúng ta dùng toán tử sizeof để quyết định số bytes được ghi. Và sau khi hàm này được thực hiện, nội dung của biến letter sẽ được khi vào file nhị phân của đối tượng "file"đó.
Chúng ta xem tiếp 1 ví dụ khác
char data[] = {'A', 'B', 'C', 'D'};
file.write(data, sizeof(data));
file.write(data, sizeof(data));
Trong ví dụ này thì đối thứ 1 là tên của mãng (data). Vì khi ta truyền tham số là tên của mãng thì tức là ta đã truyền con trỏ trỏ tới vị trí đầu tiên của mãng. Đối thứ 2 cũng có ý nghĩa tượng tự như ví dụ 1. Và sau khi gặp này thực hiện thì nội dung của mãng sẽ được ghi vào file nhị phân tương ứng với đối tượng file.
b.Read:
Hàm read thì sẽ dùng đọc vào số dữ liệu nhị phân từ file vào bộ nhớ máy tính. Dạng tổng quát là :
fileObject.read(address, size);
-Ở đây fileObject là tên của đối tượng file stream.
-address là địa chỉ đầu tiên mà vùng nhớ mà dữ liệu được đọc vào được lưu. Và đối này có thể là địa chỉ của 1 kí tự hay 1 con trỏ tới kiểu char.
-size cũng là số lượng byte trong bộ nhớ được đọc vào từ file. Và đối này bắt buộc cũng phải là số kiểu integer ( nguyên dương )
Ví dụ :
b.Read:
Hàm read thì sẽ dùng đọc vào số dữ liệu nhị phân từ file vào bộ nhớ máy tính. Dạng tổng quát là :
fileObject.read(address, size);
-Ở đây fileObject là tên của đối tượng file stream.
-address là địa chỉ đầu tiên mà vùng nhớ mà dữ liệu được đọc vào được lưu. Và đối này có thể là địa chỉ của 1 kí tự hay 1 con trỏ tới kiểu char.
-size cũng là số lượng byte trong bộ nhớ được đọc vào từ file. Và đối này bắt buộc cũng phải là số kiểu integer ( nguyên dương )
Ví dụ :
char letter;
file.read(&letter, sizeof(letter));
file.read(&letter, sizeof(letter));
Hoặc :
char data[4];
file.read(data, sizeof(data));
file.read(data, sizeof(data));
Chương trình sau sẽ minh hoạ cách sử dụng 2 hàm read and write :
// Ghi các nội dung của mảng vào tập tin.
cout << "Viết các ký tự để các tập tin. \ n";
file.write (dữ liệu, sizeof (dữ liệu));
// Đóng tệp.
file.close ();
// Mở file cho đầu vào trong chế độ nhị phân.
file.open ("test.dat", ios :: in | ios :: binary);
// Đọc nội dung của tập tin vào mảng.
cout << "Bây giờ đọc lại dữ liệu vào bộ nhớ. \ n";
file.read (dữ liệu, sizeof (dữ liệu));
// Hiển thị nội dung của mảng.
for (int count = 0; count <SIZE; đếm ++)
cout << dữ liệu [count] << "";
cout << endl;
// Đóng tệp.
file.close ();
return 0;
}
Nếu chúng ta muốn ghi các kiểu khác vào file nhị phân thì ta phải dùng cú pháp có 1 tí đặt biệt sau đây.
reinterpret_cast<dataType>(value)
Ở cú pháp trên thì dataType sẽ là kiểu dữ liệu mà chúng ta muốn ép về, và value sẽ là giá trị mà chúng ta muốn ép.
Ví dụ :
int x = 65;
file.write(reinterpret_cast<char *>(&x), sizeof(x));
file.write(reinterpret_cast<char *>(&x), sizeof(x));
Đối với mảng thì :
const int SIZE = 10;
int numbers[SIZE] = {1,2,3,4,5,6,7,8,9,10};
file.write(reinterpret_cast<charr *>(numbers), sizeof(numbers));
int numbers[SIZE] = {1,2,3,4,5,6,7,8,9,10};
file.write(reinterpret_cast<charr *>(numbers), sizeof(numbers));
Ví dụ :
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
const int SIZE = 10;
fstream file;
int numbers[SIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Open the file for output in binary mode.
file.open("numbers.dat", ios::out | ios::binary);
// Write the contents of the array to the file.
cout << "Writing the data to the file.\n";
file.write(reinterpret_cast<char *>(numbers), sizeof(numbers));
// Close the file.
file.close();
// Open the file for input in binary mode.
file.open("numbers.dat", ios::in | ios::binary);
// Read the contents of the file into the array.
cout << "Now reading the data back into memory.\n";
file.read(reinterpret_cast<char *>(numbers), sizeof(numbers));
// Display the contents of the array.
for (int count = 0; count < SIZE; count++)
cout << numbers[count] << " ";
cout << endl;
// Close the file.
file.close();
return 0;
}
Con trỏ vị trí File trong C++
Cả hai đối tượng istream và ostream đều cung cấp các hàm thành viên để xác định lại vị trí của con trỏ vị trí file (file-position pointer). Các hàm thành viên này là seekg (viết tắt của seek get) cho istream và seekp (viết tắt của seek put) cho ostream trong C++.
Tham số cho seekg và seekp thương là một long int. Tham số thứ hai có thể được xác định để chỉ dẫn hướng tìm kiếm. Hướng tìm kiếm có thể là ios::beg (mặc định) để xác định vị trí liên quan tới phần bắt đầu của một Stream, là ios::cur để xác định vị trí liên quan tới vị trí hiện tại trong một Stream hoặc là ios::end để xác định vị trí liên quan tới phần kết thúc của một Stream trong C++.
Con trỏ vị trí file là một giá trị integer mà xác định vị trí trong file, tính toán là số byte từ vị trí bắt đầu của file đó. Dưới đây là một số ví dụ để xác định vị trí của con trỏ vị trí file trong C++:
// xac dinh vi tri byte thu n cua doi tuong file doi_tuong_file.seekg( n ); // xac dinh vi tri n byte ve sau cua doi tuong file doi_tuong_file.seekg( n, ios::cur ); // xac dinh vi tri n byte bat dau tu cuoi cua doi tuong file doi_tuong_file.seekg( n, ios::end ); // xac dinh vi tri tai cuoi doi tuong file doi_tuong_file.seekg( 0, ios::end );
Nhận xét
Đăng nhận xét