Search…

Căn Bản về Đọc và Ghi File trong Ngôn Ngữ C++

01/11/20204 min read
Căn bản về thao tác đọc, ghi text file text và đọc ghi binary file trong C/C++.

Đọc và ghi file là những kĩ thuật quan trọng và sử dụng rất nhiều trong lập trình. Hầu như không có một ứng dụng nào có giá trị sử dụng mà không sử dụng đến những kĩ thuật này.

  • Khi làm một game, cần đọc file để tải map, hoặc lưu lại điểm save.
  • Khi làm một ứng dụng quản lý, việc lưu trữ các thông tin quan trọng vào file còn quan trọng hơn nữa.

Dự án càng lớn, việc xử lý file càng nhiều và phức tạp. Do đó, thành thạo trong việc thao tác với file là điều rất cần thiết.

Mở file bằng fopen()

Công việc đầu tiên là phải include thư viện stdio.h - thư viện chuẩn của C có đầy đủ các phương thức để đọc và ghi file

Cú pháp của fopen()

FILE *fopen(const char *fileName, const char *mode);

Trong đó:

  • fileName là tên của file hoặc đường dẫn đến file cần mở.
  • mode là các chế độ để xử lý file.

Ta có các mode sau:

Mode Mô tả
r Mở một file có sẵn để đọc
w Tạo file mới để ghi, nếu file có sẵn thì sẽ bị ghi mới hoàn toàn
a Mở một file để ghi từ vị trí cuối cùng của file, nếu file không tồn tại sẽ tạo mới
r+ Mở một file có sẵn để đọc và ghi
w+ Tạo file mới để đọc và ghi, nếu file có sẵn thì sẽ bị ghi mới hoàn toàn
a+ Mở một file để để đọc và ghi. Có thể đọc từ đầu file, nhưng khi ghi thì ghi từ vị trí cuối cùng của file, nếu file không tồn tại sẽ tạo mới

Ngoài ra, còn có các mode để xử lý file nhị phân như sau: rb, wb, ab, rb+, wb+, ab+, r+b, a+b

Hàm fopen() sẽ trả về NULL khi không mở được file, ví dụ trong trường hợp file bị xóa.

Đọc và ghi file thông thường

Ví dụ có file info.text nội dung như sau và muốn xuất thông tin ra màn hình:

Vinh 19
Huy 5
Amy 10
MinhHieu 4

Làm như sau:

int main()
{
	FILE *fp = fopen("info.txt", "r");
	
	if (fp == NULL)
	{
		printf("Can't open file!");
	}

	char authors[20];
	int numberOfArticles;

	while (fscanf(fp, "%s %d", authors, &numberOfArticles) != EOF)
	{
		printf("%s %d\n", authors, numberOfArticles);
	}

	fclose(fp);
	
	return 0;
}

Trong đó:

int fscanf(const char *fileName, const char *format, ...);

Hàm này có tác dụng giống như scanf(), nhưng đọc dữ liệu từ file theo format chứ không phải từ bàn phím như scanf(). fscanf() sẽ trả về EOF (End Of Flie) khi đọc đến cuối file.

Tương tự hàm fprintf() sẽ có chức năng tương tự như printf(), ghi dữ liệu vào file theo _Format.

Hàm fclose() là hàm bắt buộc phải sử dụng khi hoàn thành thao tác với 1 file - đóng file đó lại sau khi đã xử lý xong.

Đọc và ghi file theo nhị phân

Mọi file thực chất đều là file nhị phân, vì vậy khuyến khích sử dụng cách này để thao tác với file.

Cách làm như sau, xây dựng 1 hàm đọc để đọc file theo kiểu nhị phân, hàm sẽ trả về 1 mảng kiểu char để lưu toàn bộ dữ liệu của file:

void readFile(const char* filePath, char *&buff, long &fileSize)
{
    FILE *pFile = fopen(filePath, "rb");

    if (pFile == NULL)
        return;

    fseek(pFile, 0, SEEK_END);
    fileSize = ftell(pFile);
    fseek(pFile, 0, SEEK_SET);

    buff = new char[fileSize];
    fread(buff, 1, fileSize, pFile);
    fclose(pFile);
}

Chú ý một số điểm sau:

fseek(pFile, 0, SEEK_END);

Tưởng tượng có 1 con trỏ văn bản đang nhấp nháy ở trong file, hàm này sẽ đưa vị trí của con trỏ đó về cuối file.

fileSize = ftell(pFile);

Hàm ftell() sẽ trả về số bytes tính từ đầu file đến vị trí của con trỏ văn bản, do tác dụng của hàm fseek() phía trên sẽ lấy được kích thước của file.

fseek(pFile, 0, SEEK_SET); 

Hàm này sẽ đưa vị trí của con trỏ đó về đầu file.

size_t fread(void *ptr, size_t size_of_an_element,
			size_t number_of_elements,
			FILE *_File);

Dùng hàm fread() để đọc dữ liệu từ File vào mảng ptr, với tham số truyền vào là tổng kích thước cần đưa và kích thước của từng phần tử dữ liệu, ở đây dùng mảng char và muốn đưa toàn bộ nên hàm sẽ là:

fread(buff, 1, fileSize, pFile);

Để ghi một file, cần có một mảng buff đang chứa dữ liệu cần ghi vào file và đã tính toán được kích thước file, có hàm ghi file như sau:

void writeFile(const char* filePath, char *buff, long fileSize)    
{    
    FILE *pFile = fopen(filePath, "wb");
        
    if (pFile == NULL)
    {
        return;
    }

    fwrite(buff, 1, fileSize, pFile);
    fclose(pFile);
}
IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024