Kiến thức về file là một trong những kiến thức quan trọng, bài viết này trình bày chi tiết về 2 loại file là file nhị phân và file text, cũng như các kỹ thuật thao tác với file thông qua thư viện fstream
.
File nhị phân
Khái niệm
File nhị phân (hay binary file) là một tập tin máy tính, có thể chứa bất kỳ dạng dữ liệu nào và được mã hóa dưới dạng nhị phân để lưu trữ trong máy tính.
Cấu trúc
- Tập tin nhị phân thường được coi là một chuỗi các byte (8 bit).
- Có các loại tập tin nhị phân có phần header, chứa thông tin để quy định thêm các thông tin - cấu trúc dữ liệu trong file nhị phân đó.
Ứng dụng
Máy tính chỉ hiểu được mã máy (machine code còn gọi là machine language), do đó mọi dữ liệu muốn được máy tính hiểu đều phải chuyển về dạng nhị phân.
Các file nhị phân hay gặp nhất là dạng execute file (ví dụ định dạng .exe trên Windows, …). File nhị phân có thể lưu trữ được nhiều dạng dữ liệu như file text, file nhạc, file ảnh, …
File văn bản
Khái niệm
File văn bản là một tên gọi chung cho các dạng file lưu trữ dữ liệu dưới dạng ký tự, ví dụ như file text (.txt) hoặc các file lưu trữ mã nguồn (.cpp, .cs, .java).
Cấu trúc
File văn bản có cấu trúc gồm nhiều record. Mỗi một record trong file text được kết thúc bằng ký tự newline character (là ký tự \n
hoặc \r\n
).
Ứng dụng
File văn bản dùng để lưu trữ dữ liệu dạng ký tự, một số định dạng file văn bản có thể đọc dữ liệu trực tiếp như là file .txt.
Thao tác file với fstream
Thao tác với file gồm 3 giai đoạn:
MỞ FILE → ĐỌC HOẶC GHI DỮ LIỆU → ĐÓNG FILE.
Mở file
Để thao tác với file cần sử dụng thư viện #include <fstream>
, đây là thư viện C++ chuẩn nên các đối tượng và hàm được đóng gói trong namespace std
.
#include <fstream> using namespace std; int main() { const char* filePath = "D://file.txt"; ios_base::openmode mod = ios::in; fstream f; f.open(filePath, mod); // TODO: return 0; }
Để mở một file, dùng phương thức open
sau:
f.open(filePath, mod);
Trong đó:
filePath
có kiểu dữ liệu là constchar*
, là đường dẫn đến file cần mở.mod
là chế độ mở file, có một số chế độ như sau:
MOB | CHỨC NĂNG |
---|---|
ios::in | Mở file để đọc. |
ios::out | Mở file có sẵn để ghi |
ios::binary | Mở file ở chế độ nhị phân. |
ios:ate | Mở file và đặt con trỏ file vào cuối file. |
ios::app | Mở file và ghi dữ liệu vào cuối file. Nếu file không tồn tại thì tạo file mới. |
ios::trunc | Chế độ mở file, xóa bỏ hoàn toàn nội dung trong file được mở. |
Đọc và ghi dữ liệu với định dạng file nhị phân
Khi mở file mà không ghi rõ chế độ mở file, trình biên dịch sẽ chuyển về chế độ mở file text. Vì vậy, khi muốn mở ở chế độ binary, cần phải ghi rõ mod là ios::binary
.
Mở file dưới chế độ binary nghĩa là đọc thông tin theo dạng nhị phân, sử dụng hàm write và read để đọc và ghi file dưới dạng binary.
Đọc dữ liệu từ file sử dụng read
f.read(address, size);
Trong đó:
address
: Kiểu dữ liệuchar*
, là địa chỉ mà dữ liệu sẽ lưu vào sau khi đọc lên.size
: Kiểu dữ liệuint
, là số lượng byte cần đọc từ file.
Ghi dữ liệu vào file sử dụng write
f.write(address, size);
Trong đó:
address
: Kiểu dữ liệuchar*
, là địa chỉ vùng nhớ của dữ liệu được lưu vào file.size
: Kiểu dữ liệuint
, là số lượng byte cần ghi vào file.
Lưu ý:
size
là kích thước mà vùng nhớ chứa dữ liệu của quá trình đọc hay ghi.
Ví dụ:
#include <fstream> using namespace std; int main() { char data[100]; fstream f; f.open("D://text.txt", ios::in | ios::binary); if (!f) return 1; f.read(data, sizeof(data)); f.close(); return 0; }
Đọc và ghi dữ liệu với định dạng file text
Sau khi mở file, tiến hành đọc và ghi file bằng operator >>
và <<
.
Đọc file
f >> data;
Trong đó:
f
: Kiểu dữ liệufstream
, là tên biến file.data
: là tên biến lưu trữ dữ liệu cần đọc từ file.
Lưu ý:
data
: là tên biến để lưu trữ dữ liệu, có thể có các kiểu nhưint
,float
,long
,char
, ... (nhóm kiểu dữ liệu primitive).- Khi dữ liệu được đọc có kiểu khác với biến dữ liệu được lưu trữ.
- Biến lưu trữ dữ liệu kiểu số không đọc vào kiểu kí tự.
- Biến lưu trữ dữ liệu kiểu số được tự động chuyển kiểu qua lại giữa các kiểu (
float
sangint
,int
sangfloat
) bằng cơ chế chuyển kiểu ngầm định.
Ghi file
f << data;
Trong đó:
f
: Kiểu dữ liệufstream
, là tên biến file.data
: là tên biến lưu trữ dữ liệu cần ghi vào file.
Lưu ý:
- Thư viện
fstream
hỗ trợ ghi dữ liệuchar
,int
,long
, ... (nhóm dữ liệu primitive), không hỗ trợ ghi kiểu dữ liệu mở rộng (struct
,class
, ...).
* Ngoài việc sử dụng operator, có thể tìm hiểu thêm việc sử dụng hàm get
và hàm put
để lấy thông tin từ file.
Đóng file
Sau khi thao tác với file, đóng file bằng phương thức:
f.close()
Đóng file giúp bảo toàn được dữ liệu đang tiến hành lưu trữ. Đồng thời tránh khỏi một số lỗi không đáng có như 2 thread cùng mở 1 file.
Các ví dụ
Đọc dữ liệu
Thực hiện đọc dữ liệu từ 2 file text, và đọc dữ liệu có các kiểu khác nhau trong cùng một file text.
Trong ví dụ này, có 2 file text:
- IntroUniversity.txt: lưu trữ tên trường đại học của sinh viên.
- StorageStudentInfo.txt: lưu thông tin sinh viên học tại trường đó, gồm tên và mã số sinh viên.
File IntroUniversity.txt:
University of Information Technology
File StorageStudentInfo.txt:
Trung 10 Nam 4 Bac 8
Mã nguồn thực thi:
#include <iostream> #include <fstream> #include <string> using namespace std; void printStudentInfo(string studentName[], int studentID[], int numberOfStudents) { for (int i = 0; i < numberOfStudents; ++i) { cout << studentID[i] << "\t" << studentName[i] << endl; } } int main() { fstream fs; string nameOfUniversity; string nameOfStudents[3]; int idOfStudents[3]; // Đoạn mã đọc thông tin trường đại học. fs.open("IntroUniversity.txt"); if (!fs) return -1;
fs >> nameOfUniversity; cout << nameOfUniversity << endl; fs.close(); // Đoạn mã đọc thông tin sinh viên. fs.open("StorageStudentInfo.txt"); if (!fs) return -1; int index = 0; while (fs) { fs >> nameOfStudents[index] // Đọc thông tin sinh viên từ file. >> idOfStudents[index]; index++; } fs.close(); printStudentInfo(nameOfStudents, idOfStudents, 3); return 0; }
Ghi dữ liệu
#include <fstream> using namespace std; int main() { fstream f; // Ghi dữ liệu vào file int numberData = 1024; f.open("text.txt"); f << numberData; f.close(); return 0; }