Chào các bạn đang theo dõi khóa học lập trình trực tuyến từ ngữ C++.
Trong bài học này, tất cả chúng ta sẽ cùng tìm hiểu về các khái niệm về File và phương pháp để thao tác với File trong từ ngữ lập trình C/C++.
File
Nếu PC của các bạn có ổ cứng, hoặc các bạn có USB hoặc bất kỳ thiết bị lưu trữ nào thì chắc nịch các bạn đã từng làm việc với File. Khi các bạn chơi một game offline, thông tin nhân vật, điểm số, … sẽ được lưu trữ trong File để khi chương trình game bị tắt đi thì các bạn không phải chơi lại từ đầu. Khi các bạn thiết lập cấu hình cho một PM và tắt đi, cấu hình đó được lưu vào File để lần làm việc tiếp theo sẽ sử dụng. Hay khi các bạn biên dịch một chương trình C++ trên Visual Studio 2015, C++ Compiler của Visual studio sẽ đọc mã nguồn các bạn đã viết trong các file *.cpp
để xác minh lỗi và dịch chúng sang file *.obj
. Ngay cả hệ điều hành Windows mà các bạn đang sử dụng cũng là tập hợp của rất nhiều file được lưu trữ bên trong phân vùng ổ đĩa dùng cho Hệ điều hành…
Này là một vài ví dụ cho thấy sự tồn tại của File trong PC. Vậy thì tất cả chúng ta đã thao tác với những File đó như vậy nào?
Làm việc với File tất cả chúng ta chỉ có các thao tác cơ bản như: tạo file mới, đọc dữ liệu trong file, ghi dữ liệu vào file, xóa file… Và tất cả chúng ta làm điều đó hằng ngày, khi tất cả chúng ta chơi game, khi xem phim trên PC, … và ngay cả khi tất cả chúng ta lập trình, mã nguồn của tất cả chúng ta được lưu xuống File mã nguồn khi nhấn tổ hợp phím Ctrl + S.
Theo khái niệm trên Wikipedia về computer file: Một file trên PC là một tài nguyên dùng để lưu trữ thông tin lâu dài, sử dụng cho các chương trình PC.
Không khác gì như việc lưu trữ dữ liệu tạm thời trên RAM, file cũng lưu trữ dữ liệu dưới dạng nhị phân (0 hoặc 1), tuy nhiên tùy vào định dạng của file và cách chuyển hóa của mỗi PM đọc file mà tất cả chúng ta có những kiểu thông tin khác nhau. Ví dụ file .png thì được chuyển về dạng hình ảnh, PM Microsoft Word chuyển dãy bit nhị phân về dạng text…
Trong từ ngữ lập trình C/C++: File là kiểu đối tượng, nó xác nhận một stream và chứa các thông tin thiết yếu để điều khiển, bao gồm một con trỏ trỏ đến buffer của nó, các chỉ mục và trạng thái của nó.
Các bạn có thể hiểu File (trong từ ngữ lập trình C/C++) là một kiểu đối tượng mà thông qua nó tất cả chúng ta có thể thao tác với dữ liệu được lưu trữ bên trong File (chứ không phải là một File trên PC).
Để các bạn không bị nhầm lẫn, mình đang nói về kiểu dữ liệu FILE được khái niệm trong thư viện cstdio (hay stdio.h) mà có thể các bạn đã từng học trong từ ngữ C. Tất cả chúng ta sẽ học cách sử dụng các Stream để thao tác với file thay vì sử dụng kiểu dữ liệu FILE trong các bài học sau, nhưng mình nghĩ kiểu dữ liệu FILE trong thư viện cstdio cũng có những ưu thế riêng của nó nên mình không bỏ qua bài học này.
Làm việc với FILE type trong C/C++
Trong bài học này, mình sẽ hướng dẫn các bạn thực hiện các thao tác như mở file, đọc và ghi dữ liệu trong file… Tất cả chúng ta cần làm việc trên một file rõ ràng nào đó nên mình sẽ tạo một file với tên file là my_document.txt
trong thư mục Desktop có đường dẫn trên máy mình là: C:/Users/ADMIN/Desktop/my_document.txt
Để làm việc với file, tất cả chúng ta cần biết vị trí của file (thông qua đường dẫn) để con trỏ kiểu FILE có thể tạo được luồng dữ liệu giữa người dùng và file trên thiết bị lưu trữ.
int
main
()
{
const
char
*filePath = "C:/Users/ADMIN/Desktop/my_document.txt"
;
FILE *file;
return
;
}
Open file
Để mở một file, các bạn có thể sử dụng hàm fopen được khái niệm trong thư viện cstdio:
FILE
* fopen(const
char
*file
, const
char
*mode);
Hàm fopen cho phép tạo một kết nối đến file với đường dẫn được lưu trữ bởi tham số thứ nhất. Nếu file không tồn tại, file mới sẽ được tạo ra với tên file như trong đường dẫn. Tham số thứ hai xác nhận kiểu truy cập vào file. Bảng dưới đây liệt kê các mode dùng để mở một file trong C:
Nếu mở file thành công, một địa chỉ của một đối tượng kiểu FILE sẽ được trả về. Nếu mở file thất bại thì trả về NULL.
const
char
*filePath = "C:/Users/ADMIN/Desktop/my_document.txt"
;
FILE *file;
file = fopen(filePath, "r"
);
if
(!file)
std
::cout
<< "Can not open this file"
<< std
::endl
;
else
std
::cout
<< "File is opened"
<< std
::endl
;
Trong đoạn chương trình trên, mình mở file đã tạo sẵn trong thư mục Desktop với mode “r” (chỉ dùng để đọc dữ liệu).
Các bạn cần lưu ý rằng file trong PC tồn tại ở 2 dạng: file văn bản và file bị mã hóa.
File văn bản là những file mà các bạn có thể đọc được khi mở bằng các trình soạn thảo văn bản, thông thường những file này được định dạng Unicode (hoặc những định dạng dùng cho văn bản khác).
File bị mã hóa (thường gọi là file nhị phân) không thể đọc được khi mở file bằng các trình soạn thảo văn bản. Sử dụng File bị mã hóa giúp tất cả chúng ta bảo mật dữ liệu tốt hơn File văn bản.
Các mode mà mình đã liệt kê ở bảng trên chỉ dùng để thao tác với file văn bản. Khi thao tác với file bị mã hóa (file nhị phân), các bạn cần nối thêm kí tự b (binary) vào ngay sau mode mà các bạn chọn. Ví dụ: “rb”, “wb”, “ab”, “rb+”, “r+b”, …
Close file
Sau thời điểm thao tác với file xong, các bạn cần đóng file lại để tránh những lỗi phát sinh ngoài ý muốn. Để đóng file, tất cả chúng ta sử dụng hàm fclose:
int
fclose(FILE
*file
);
Trong số đó, file là con trỏ được dùng để lưu trữ địa chỉ của đối tượng FILE đang mở. Nếu đóng file thành công thì trả về giá trị 0, trái lại trả về EOF (End of file).
const
char
*filePath = "C:/Users/ADMIN/Desktop/my_document.txt"
;
FILE *file;
file = fopen(filePath, "r"
);
if
(!file)
std
::cout
<< "Can not open this file"
<< std
::endl
;
else
std
::cout
<< "File is opened"
<< std
::endl
;
fclose(file);
Hàm fclose sẽ giải phóng toàn bộ dữ liệu chưa được xử lý trên file nếu chúng vẫn còn lưu trong buffer, đóng file lại, và giải phóng toàn bộ vùng nhớ mà đối tượng FILE sử dụng.
Write data to file
Các bạn đã thực hiện được thao tác mở và đóng file, nhưng lúc này, file mới tạo ra vẫn chưa có dữ liệu nên mình sẽ thực hiện thao tác ghi dữ liệu vào file trước. Để mở file cho cơ chế ghi file, tất cả chúng ta có các mode “w”, “r+”, “w+”, “a”, “a+”. Mình chỉ muốn ghi dữ liệu nên mình sẽ chọn mode “w”.
Nhưng trước hết, tất cả chúng ta nên tách thao tác ghi file ra một hàm riêng có dạng:
void
writeToFile(FILE
*file
);
Hàm này sẽ được gọi sau thời điểm mở file và trước khi đóng file.
const
char
*filePath = "C:/Users/ADMIN/Desktop/my_document.txt"
;
FILE *file;
file = fopen(filePath, "w"
);
if
(!file)
std
::cout
<< "Can not open this file"
<< std
::endl
;
else
std
::cout
<< "File is opened"
<< std
::endl
;
writeToFile(file);
fclose(file);
Hiện giờ, tất cả chúng ta chỉ quan tâm đến nội dung bên trong hàm writeToFile.
Để ghi dữ liệu vào file, tất cả chúng ta có các hàm đã được khái niệm sẵn trong thư viện cstdio như sau:
-
fputc:
int
fputc
(
int
c, FILE *f);Hàm fputc sẽ ghi ký tự có mã ASCII là c vào file được trỏ đến bởi con trỏ f. Giá trị trả về là EOF nếu ghi dữ liệu thất bại, trả về mã ASCII của kí tự được ghi vào nếu thực hiện thành công.
Ví dụ:
void
writeToFile
(FILE *file)
{int
c = fputc('A'
, file);std
::cout
<< c <<std
::endl
; }Sau thời điểm chạy chương trình xong, các bạn mở file my_document.txt trên Desktop lên sẽ thấy kí tự ‘A’ đã được ghi vào, đồng thời trên console cũng in ra mã ASCII của kí tự ‘A’.
-
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ự ‘