Chào chúng ta đang theo dõi khóa đào tạo và huấn luyện lập trình trực tuyến ngữ điệu C++.

Bạn đang xem: Bài Tập Đọc File Và Ghi File Trong Lập Trình C Và Ghi File Trong C

Trong bài học này, chúng ta sẽ cùng tìm hiểu về các khái niệm về tệp tin và phương pháp để thao tác với tệp tin trong ngôn ngữ lập trình C/C++.

File

Nếu máy vi tính của các bạn có ổ cứng, hoặc chúng ta có USB hoặc ngẫu nhiên thiết bị tàng trữ nào thì dĩ nhiên chắn các bạn đã từng thao tác với File. Khi chúng ta chơi một game offline, thông tin nhân vật, điểm số, ... Sẽ tiến hành lưu trữ trong File nhằm khi công tác game bị tắt đi thì các bạn không nên chơi lại từ bỏ đầu. Khi chúng ta cài đặt thông số kỹ thuật cho 1 phần mềm cùng tắt đi, thông số kỹ thuật đó được lưu lại vào File để lần thao tác làm việc tiếp theo đang sử dụng. Hay khi các bạn biên dịch một lịch 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 những file *.gameviethot.com để chất vấn lỗi cùng dịch bọn chúng sang tệp tin *.obj. Trong cả hệ quản lý và điều hành Windows mà các bạn đang áp dụng cũng là tập hợp của không ít file được giữ trữ phía bên trong phân vùng ổ đĩa sử dụng cho Hệ điều hành...

Đó là một trong vài ví dụ cho biết sự mãi sau của tệp tin trong thiết bị tính. Vậy thì chúng ta đã thao tác với hầu hết File đó như vậy nào?

Làm việc với File họ chỉ tất cả các thao tác làm việc cơ phiên bản như: tạo nên file mới, đọc dữ liệu trong file, ghi dữ liệu vào file, xóa file... Và chúng ta làm điều ấy hằng ngày, khi chúng ta chơi game, lúc chứng kiến tận mắt phim trên trang bị tính, ... Và ngay cả khi bọn họ lập trình, mã mối cung cấp của chúng ta được giữ xuống tệp tin mã nguồn lúc nhấn tổng hợp phím Ctrl + S.

Theo tư tưởng trên Wikipedia về computer file: Một file trên laptop là một tài nguyên dùng để lưu trữ tin tức lâu dài, sử dụng cho những chương trình thứ tính.

Cũng y hệt như việc tàng 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 vậy tùy vào format của file cùng cách biến đổi của mỗi ứng dụng đọc file mà bọn họ có mọi kiểu thông tin khác nhau. Ví dụ tệp tin .png thì được chuyển về mẫu thiết kế ảnh, ứng dụng Microsoft Word gửi dãy bit nhị phân về dạng text...

Trong ngôn ngữ lập trình C/C++: tệp tin là hình dạng đối tượng, nó khẳng định một stream và chứa các thông tin quan trọng để điều khiển, bao gồm một con trỏ trỏ mang đế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 tệp tin (trong ngữ điệu lập trình C/C++) là 1 kiểu đối tượng người sử dụng mà trải qua nó chúng ta có thể thao tác với dữ liệu được lưu trữ phía bên trong File (chứ không phải là 1 trong File trên vật dụng tính).

Để các bạn không bị nhầm lẫn, mình đang nói tới kiểu dữ liệu FILE được có mang trong thư viện cstdio (hay stdio.h) mà tất cả thể chúng ta đã từng học trong ngôn từ C. Bọn họ sẽ học giải pháp sử dụng những Stream để làm việc với file vắt vì thực hiện kiểu tài liệu FILE trong số bài học sau, nhưng lại mình nghĩ kiểu dữ liệu FILE trong tủ sách cstdio cũng có những điểm mạnh riêng của nó buộc phải mình không vứt qua bài học kinh nghiệm này.

Làm việc với tệp tin type trong C/C++

Trong bài học này, mình vẫn hướng dẫn chúng ta thực hiện tại các thao tác làm việc như mở file, đọc và ghi dữ liệu trong file... Họ cần thao tác trên một file cụ thể nào đó đề xuất mình sẽ tạo một file với tên file là my_document.txt trong folder Desktop có đường truyền trên thứ mình là: C:/Users/ADMIN/Desktop/my_document.txt

Để thao tác làm việc với file, họ cần biết địa chỉ của tệp tin (thông qua mặt đường dẫn) để bé trỏ vẻ bên ngoài FILE rất có thể tạo được luồng tài liệu giữa người tiêu dùng và file trên thứ lưu trữ.

#include #include int main()const char *filePath = "C:/Users/ADMIN/Desktop/my_document.txt";FILE *file;return 0;Open fileĐể mở một file, các bạn có thể sử dụng hàm fopen được định nghĩa 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 băng thông được lưu trữ bởi tham số lắp thêm nhất. Nếu tệp tin không tồn tại, file mới sẽ được tạo ra với tên file như trong con đường dẫn. Tham số trang bị hai xác định kiểu truy vấn vào file. Bảng tiếp sau đây liệt kê các mode dùng để mở một tệp tin trong C:


*

Nếu mở tệp tin thành công, một địa chỉ của một đối tượng người sử dụng kiểu FILE sẽ được trả về. Giả dụ mở file thảm 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 xuất hiện this file" << std::endl;elsestd::cout << "File is opened" << std::endl;Trong đoạn chương trình trên, bản thân mở tệp tin đã tạo nên sẵn trong thư mục Desktop với mode "r" (chỉ dùng để đọc dữ liệu).

Các chúng ta cần xem xét rằng file trong máy vi tính tồn tại ở cả 2 dạng: tệp tin văn bạn dạng và tệp tin bị mã hóa.

File văn bản là phần lớn file cơ mà các bạn có thể đọc được lúc mở bằng những trình soạn thảo văn bản, thông thường những tệp tin này được định hình Unicode (hoặc phần nhiều định dạng sử dụng cho văn bạn dạng khác).

File bị mã hóa (thường call là file nhị phân) bắt buộc đọc được khi mở tệp tin bằng những trình biên soạn thảo văn bản. Sử dụng File bị mã hóa giúp bọn họ bảo mật dữ liệu xuất sắc hơn tệp tin văn bản.

Các mode mà mình đã liệt kê ngơi nghỉ bảng bên trên chỉ dùng để thao tác với file văn bản. Khi làm việc với tệp tin 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 lập tức sau mode mà chúng ta chọn. Ví dụ: "rb", "wb", "ab", "rb+", "r+b", ...

Close file

Sau khi thao tác làm việc với file xong, các bạn cần đóng file lại để tránh các lỗi vạc sinh xung quanh ý muốn. Để đóng góp file, chúng ta sử dụng hàm fclose:

int fclose(FILE *file);Trong đó, file là bé trỏ được dùng để lưu trữ showroom của đối tượng FILE đang mở. Nếu đóng góp file thành công xuất sắc 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;elsestd::cout << "File is opened" << std::endl;fclose(file);Hàm fclose sẽ giải phóng tất cả dữ liệu không được xử lý trên file nếu chúng vẫn còn đấy lưu vào buffer, đóng góp file lại, và giải phóng toàn khu vực nhớ mà đối tượng FILE sử dụng.

Write data lớn file

Các các bạn đã triển khai được thao tác mở và đóng file, mà lại lúc này, tệp tin mới tạo ra vẫn chưa có dữ liệu phải mình vẫn thực hiện làm việc ghi tài liệu vào file trước. Để mở tệp tin cho chính sách ghi file, chúng ta có các mode "w", "r+", "w+", "a", "a+". Tôi chỉ muốn ghi dữ liệu nên mình sẽ chọn mode "w".

Nhưng trước hết, họ nên bóc 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ở tệp tin và trước lúc đóng file.

const char *filePath = "C:/Users/ADMIN/Desktop/my_document.txt";FILE *file;file = fopen(filePath, "w");if (!file)std::cout << "Can not mở cửa this file" << std::endl;elsestd::cout << "File is opened" << std::endl;writeToFile(file);fclose(file);Bây giờ, bọn họ chỉ lưu ý đến nội dung bên trong hàm writeToFile.

Để ghi tài liệu vào file, họ có những hàm sẽ được quan niệm sẵn trong thư viện cstdio như sau:

fputc:

int fputc(int c, file *f);Hàm fputc đã ghi cam kết tự bao gồm mã ASCII là c vào file được trỏ mang lại bởi con trỏ f. Giá trị trả về là EOF nếu như ghi tài liệu thất bại, trả về mã ASCII của kí từ bỏ đượ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 khi chạy lịch trình xong, các bạn mở file my_document.txt bên trên Desktop lên đã thấy kí trường đoản cú "A" đã có được ghi vào, mặt khác 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ỏ cho bởi nhỏ trỏ f cho tới khi gặp mặt kí trường đoản cú "".

Ví dụ:

void writeToFile(FILE *file)int c = fputs("hello", file);Sau khi chạy chương trình, các bạn mở file my_document.txt sống thư mục Desktop đã thấy kí trường đoản cú "A" dịp nãy không thể nữa, vắt vào sẽ là chuỗi kí từ "hello".

Xem thêm:

Read data from file

Đầu tiên mình sẽ tạo một hàm khác mang tên là readFromFile như sau:

void readFromFile(FILE *file)//read dataĐể làm những ví dụ trong phần này, mình sẽ hotline hàm này sau khi đã gọi hàm writeToFile.

const char *filePath = "C:/Users/ADMIN/Desktop/my_document.txt";FILE *file;file = fopen(filePath, "w+");if (!file)std::cout << "Can not mở cửa this file" << std::endl;elsestd::cout << "File is opened" << std::endl;writeToFile(file);readFromFile(file);fclose(file);Lúc này, file của họ được mở nhằm vừa đọc với ghi file, buộc phải mình sẽ thực hiện mode "w+" (hoặc "r+").

Và dưới đây là một số hàm được tư tưởng 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 phát âm ra một kí tự vào file, internal tệp tin position indicator vẫn chuyển mang đến kí tự tiếp theo. Quý giá trả về là mã ASCII của kí tự đang đọc được.

Ví dụ:

void readFromFile(FILE *file)std::cout << (char)fgetc(file) << std::endl;fgets:

char* fgets(char *buf, int n, tệp tin *f);Hàm fgets gọi từ tệp tin ra (n - 1) kí tự, vấn đề đọc dữ liệu sẽ ảnh hưởng dừng nếu phát âm được kí trường đoản cú new line " " hoặc EOF. Chuỗi kí tự gọi được sẽ lưu vào vùng lưu giữ được làm chủ bởi bé trỏ buf, nếu đọc dữ liệu thành công thì trả về showroom của buf, trái lại trả về NULL.

Ví dụ:

void readFromFile(FILE *file)char str<255>;std::cout << fgets(str, 255, file) << std::endl;std::cout << str << std::endl;Kết quả phát âm file được lưu lại vào mảng kí trường đoản cú str.

Reposition stream position indicator

Ghép các ví dụ làm việc trên lại, chúng ta có một chương trình đơn giản và dễ dàng minh họa cho việc ghi file và đọc từng dòng tài liệu (line by line) đã được ghi vào file như sau:

#include #include #include void writeToFile(FILE *file)for (int i = 1; i <= 5; i++)fprintf(file, "This is an example line %d ", i);void readFromFile(FILE *file)char str<255>;while (fgets(str, 255, file) != NULL)std::cout << str;int main()const char *filePath = "C:/Users/ADMIN/Desktop/my_document.txt";FILE *file;file = fopen(filePath, "w+");if (!file)std::cout << "Can not xuất hiện this file" << std::endl;elsestd::cout << "File is opened" << std::endl;writeToFile(file);readFromFile(file);fclose(file);return 0;Tuy nhiên, tác dụng cho ra màn hình không giống như mong muốn.

Nguyên nhân là khi bọn họ gọi hàm writeToFile cùng truyền vào đó bé trỏ file, bài toán ghi file đã khiến internal tệp tin position indicator trỏ mang lại vị trí sau cùng trong file. Sau khi quay quay trở về hàm main, chúng ta tiếp tục gọi hàm readFromFile với một con trỏ file. Như vậy, lúc bọn họ đọc file thì bọn họ lại bước đầu đọc tại vị trí chấm dứt file.

Để khắc phục và hạn chế điều này, chúng ta cần đóng con trỏ file lại với mở tạo nên một liên kết mới bởi hàm fopen cùng với mode dùng để làm đọc file. Tuy nhiên, làm do vậy thì code xử trí của họ sẽ nhiều năm hơn. Thư viện cstdio đã cung cấp cho bọn họ hàm fseek để đổi khác vị trí trỏ cho trong file của internal tệp tin position indicator.

int fseek(FILE *f, long int offset, int origin);Trong đó:

f là con trỏ trỏ đến đối tượng người tiêu dùng FILE đang mở.

offset là số bytes được thêm vào đó tính từ địa điểm origin.

origin là địa điểm đặt bé trỏ trong file:

*

Như vậy, sau khi gọi hàm writeToFile xong, bọn họ cần di chuyển internal file position indicator về đầu file bằng cách như sau:

writeToFile(file);fseek(file, 0, SEEK_SET);readFromFile(file);Sau đó chạy công tác thì thấy tài liệu in ra màn hình hiển thị đúng tựa như các gì bọn họ đã ghi vào file.

Determine form size of nội dung of file

Đôi khi họ cần đọc cục bộ nội dung của file vào trong 1 vùng nhớ trên Heap, họ sẽ cần phải biết trước kích thước nội dung có trong tệp tin để cấp phát đủ vùng nhớ trước khi đọc file. Tủ sách cstdio chỉ cung cấp cho bọn họ hàm ftell:

long int ftell(FILE *f);Hàm này đã trả về vị trí của file indicator sẽ trỏ mang lại trong file (số bytes của nội dung file nhưng mà indicator đã để mắt tới qua).

Như vậy, các bạn cũng có thể đọc kích thước của văn bản trong file bằng phương pháp dịch internal tệp tin position indicator về vị trí sau cùng trong file rồi điện thoại tư vấn hàm ftell:

__int64 size_of_file(FILE *file)fseek(file, 0, SEEK_END);__int64 kích cỡ = ftell(file);fseek(file, 0, SEEK_SET);return size;Binary I/O functionsDưới đấy là 2 hàm dùng để làm đọc cùng ghi dữ liệu chỉ cần sử dụng cho mode nhị phân.

size_t fwrite(const void *ptr, size_t size, size_t count, tệp tin *f);Hàm fwrite dùng để ghi dãy bit vào vùng nhớ được cai quản bởi con trỏ ptr vào file đang được trỏ vì f, form size là số bytes vẫn copy từ bỏ vùng lưu giữ của ptr và count là chu kỳ ghi vùng nhớ đó xuống file.

Hàm fwrite không thân thương vùng nhớ của chúng ta có định dạng gì, nó quan lại tâm size vùng nhớ bắt buộc đọc và cứ cầm cố copy toàn bộ các bits và file, mỗi lần sẽ copy 1 block of bit.

size_t fread(void *ptr, size_t size, size_t count, tệp tin *f);Hàm fread sẽ copy count lần block of bits có kích thước là size, đưa vào vùng ghi nhớ được trỏ đến bởi vì ptr, từ file vẫn được cai quản bởi f.

Sau khi gọi hàm fread, internal tệp tin position indicator sẽ di chuyển tới (size * count) bytes từ vị trí bắt đầu đọc file.

Ví dụ:

#include #include #include void writeToFile(FILE *file)char *s = "Hello everyone!";fwrite(s, strlen(s), 1, file);void readFromFile(FILE *file)void *ptr = operator new(255); //allocate 255 bytes on Heapfread(ptr, 255, 1, file);(static_cast(ptr))<255> = "";std::cout << static_cast(ptr) << std::endl;int main()const char *filePath = "C:/Users/ADMIN/Desktop/my_document.txt";FILE *file;file = fopen(filePath, "w+b"); //use binary modeif (!file)std::cout << "Can not xuất hiện this file" << std::endl;elsestd::cout << "File is opened" << std::endl;writeToFile(file);fseek(file, 0, SEEK_SET);readFromFile(file);fclose(file);return 0;Chạy chương trình trên đến ra kết quả là không hề ít kí từ rác.

Như chúng ta thấy, hàm fread gọi đúng 255 bytes trong file để đưa vào vùng nhớ của ptr nên những giá trị quá xuất hiện. Vào trường thích hợp này, dùng hàm fread với fwrite không phù hợp. Hàm fread và fwrite hay được dùng để làm đọc với ghi tài liệu kiểu struct vào file.

Write and read structs

Mình vẫn giữ lại nguyên cấu tạo chương trinh như trên với chỉ chuyển đổi code vào hàm writeToFile và readFromFile.

Trước hết, mình sinh sản một struct đơn giản dễ dàng như sau:

struct Employee__int32 ID;char name<50>;;Kích thước của struct này là 56 bytes (không buộc phải là 54 bytes vì chưng cách tổ chức triển khai dữ liệu trong struct còn liên quan đến tư tưởng struct alignment). Như vậy là mỗi unit tất cả kiểu Employee được tạo nên đều chiếm một vùng nhớ có kích cỡ 56 bytes.

Các chúng ta thử tưởng tượng nếu chúng ta sử dụng các hàm ghi file như fputs, fprintf... Thì kích cỡ tên của mọi cá nhân sẽ khác nhau dẫn đến họ không có một định dạng phổ biến để dễ cai quản nhiều Employee vào file. Việc đặt chúng nó vào trong 1 struct giúp họ đọc và ghi file thuận lợi hơn nhiều.

Dưới đó là một đoạn chương trình mẫu mã cho bài toán xử lý tệp tin để quản lý 3 Employee:

#include #include #include struct Employee__int32 ID;char name<50>;;Employee emps<3> = 1, "Le Tran Dat" , 2, "Ngo Doan Tuan" , 3, "Le Dinh Huy" ;void writeToFile(FILE *file)for (int i = 0; i < 3; i++)fwrite(&emps, sizeof(Employee), 1, file);void readFromFile(FILE *file)Employee emp;for (int i = 0; i < 3; i++)fread(&emp, sizeof(Employee), 1, file);std::cout << emp.ID << std::endl;std::cout << emp.name << std::endl;std::cout << "================================" << std::endl;int main()const char *filePath = "C:/Users/ADMIN/Desktop/my_document.txt";FILE *file;file = fopen(filePath, "w+b"); //use binary modeif (!file)std::cout << "Can not mở cửa this file" << std::endl;elsestd::cout << "File is opened" << std::endl;writeToFile(file);fseek(file, 0, SEEK_SET);readFromFile(file);fclose(file);return 0;Các các bạn chạy thử đoạn chương trình trên giúp xem kết quả.

Bây giờ chúng ta cùng mở tệp tin my_document.txt trong thư mục Desktop giúp thấy thử văn bản trong file như vậy nào: