File i/o trong c

Chào các bạn đang theo dõi khóa đào tạo và huấn luyện lập trình trực tuyến ngôn từ C++.

Bạn đang xem: File i/o trong c

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

File

Nếu laptop 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ị lưu trữ nào thì cứng cáp 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ữ vào File để khi công tác game bị tắt đi thì chúng ta không đề nghị chơi lại tự đầu. Khi chúng ta cài đặt thông số kỹ thuật cho 1 phần mềm với tắt đi, cấu hình đó được lưu vào File nhằm 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 công tác C++ bên trên Visual Studio 2015, C++ Compiler của Visual studio sẽ đọc mã nguồn các bạn đã viết trong số file *.mocmien.info để bình chọn lỗi và dịch bọn chúng sang tệp tin *.obj. Ngay cả hệ điều hành quản lý Windows mà các bạn đang sử dụng cũng là tập hợp của không ít file được giữ trữ bên phía trong phân vùng ổ đĩa cần sử dụng cho Hệ điều hành...

Đó là 1 trong vài ví dụ cho biết sự vĩnh cửu của file trong vật dụng tính. Vậy thì họ đã thao tác làm việc với hầu hết File đó như thế nào?

Làm việc với File họ chỉ bao gồm các thao tác làm việc cơ bạn dạng 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à bọn họ làm điều ấy hằng ngày, khi bọn họ chơi game, lúc chứng kiến tận mắt phim trên vật dụng tính, ... Và trong cả khi bọn họ lập trình, mã nguồn của chúng ta được lưu xuống tệp tin mã nguồn khi nhấn tổ hợp phím Ctrl + S.

Theo có mang trên Wikipedia về computer file: Một tệp tin trên laptop 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 thứ tính.

Cũng giống hệt như việc lưu trữ dữ liệu tạm thời trên RAM, tệp tin cũng lưu trữ dữ liệu bên dưới dạng nhị phân (0 hoặc 1), tuy vậy tùy vào định dạng của file và cách biến đổi của mỗi ứng dụng đọc tệp tin mà họ có số đông kiểu tin tức khác nhau. Ví dụ tệp tin .png thì được gửi về kiểu dáng ảnh, ứng dụng Microsoft Word chuyển dãy bit nhị phân về dạng text...

Trong ngữ điệu lập trình C/C++: tệp tin là loại đối tượng, nó xác định một stream cùng chứa những thông tin cần thiết để điều khiển, bao gồm 1 con trỏ trỏ mang lại buffer của nó, những chỉ mục và trạng thái của nó.

Các bạn có thể hiểu file (trong ngữ điệu lập trình C/C++) là một kiểu đối tượng người sử dụng mà thông qua nó chúng ta có thể thao tác với dữ liệu được lưu lại trữ phía bên trong File (chứ ko phải là 1 trong những File trên máy tính).

Để chúng ta không bị nhầm lẫn, bản thân đang nói về kiểu dữ liệu FILE được quan niệm trong thư viện cstdio (hay stdio.h) mà có thể các bạn đã từng học tập trong ngôn từ C. Họ sẽ học phương pháp sử dụng những Stream để thao tác làm việc với file cố kỉnh vì sử dụng kiểu dữ liệu FILE trong những bài học sau, mà lại mình nghĩ về kiểu dữ liệu FILE trong tủ sách cstdio cũng có những ưu thế riêng của nó phải mình không vứt qua bài học kinh nghiệm này.

Làm câu hỏi với file type trong C/C++

Trong bài học kinh nghiệm này, mình đang hướng dẫn các bạn thực hiện các làm việc như mở file, đọc với ghi tài liệu trong file... Họ cần thao tác trên một file rõ ràng nào đó đề nghị mình sẽ khởi tạo một file với tên file là my_document.txt trong thư mục Desktop có đường truyền trên trang bị mình là: C:/Users/ADMIN/Desktop/my_document.txt

Để làm việc với file, chúng ta cần biết vị trí của file (thông qua mặt đường dẫn) để con trỏ đẳng cấp FILE có thể tạo được luồng dữ liệu giữa người tiêu dùng và file trên đồ vật 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 chúng ta cũng có thể sử dụng hàm fopen được tư tưởng trong tủ sách cstdio:

FILE* fopen(const char *file, const char *mode);Hàm fopen chất nhận được tạo một kết nối đến file với băng thông được tàng trữ bởi tham số vật dụng nhất. Nếu tệp tin không tồn tại, file new sẽ được tạo ra với tên tệp tin như trong mặt đường dẫn. Tham số sản phẩm công nghệ hai xác minh kiểu truy cập vào file. Bảng tiếp sau đây liệt kê các mode dùng để làm mở một tệp tin trong C:


*

Nếu mở file thành công, một địa chỉ cửa hàng của một đối tượng người tiêu dùng kiểu FILE sẽ được trả về. Giả dụ mở file lose 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 công tác trên, bản thân mở file đã tạo nên sẵn trong thư mục Desktop với mode "r" (chỉ dùng làm đọc dữ liệu).

Các các bạn cần để ý rằng file trong máy tính xách tay tồn tại ở hai dạng: file văn bạn dạng và tệp tin bị mã hóa.

File văn phiên bản là đa số file nhưng các chúng ta cũng có thể đọc được lúc mở bằng những trình biên soạn thảo văn bản, thông thường những tệp tin này được format Unicode (hoặc những định dạng dùng cho văn bạn dạng khác).

File bị mã hóa (thường gọi là file nhị phân) quan trọng đọc được khi mở file bằng các trình biên soạn thảo văn bản. áp dụng File bị mã hóa giúp 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ê sinh sống bảng trên chỉ dùng để làm 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), chúng ta cần nối thêm kí từ b (binary) vào ngay lập tức sau mode mà các bạn chọn. Ví dụ: "rb", "wb", "ab", "rb+", "r+b", ...

Close file

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

int fclose(FILE *file);Trong đó, tệp tin là bé trỏ được dùng để làm lưu trữ showroom của đối tượng người tiêu dùng FILE vẫn mở. Nếu đóng góp file thành công xuất sắc thì trả về cực hiếm 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 vẫn giải phóng toàn bộ dữ liệu không được xử lý trên tệp tin nếu chúng vẫn còn đó lưu vào buffer, đóng file lại, và giải phóng toàn khu vực nhớ mà đối tượng người dùng FILE sử dụng.

Write data lớn file

Các chúng ta đã thực hiện được làm việc mở với đóng file, nhưng mà lúc này, tệp tin mới tạo nên vẫn chưa xuất hiện dữ liệu buộc phải mình vẫn thực hiện thao tác ghi dữ liệu vào file trước. Để mở file cho cơ chế ghi file, chúng ta có những 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, chúng ta nên bóc tách thao tác ghi tệp tin ra một hàm riêng gồm dạng:

void writeToFile(FILE *file);Hàm này sẽ được gọi sau khi 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;elsestd::cout << "File is opened" << std::endl;writeToFile(file);fclose(file);Bây giờ, chúng ta chỉ cân nhắc nội dung phía bên trong hàm writeToFile.

Để ghi tài liệu vào file, bọn họ có những hàm vẫn được có mang sẵn trong tủ sách cstdio như sau:

fputc:

int fputc(int c, tệp tin *f);Hàm fputc đã ghi cam kết tự bao gồm mã ASCII là c vào file được trỏ đến bởi bé trỏ f. Quý hiếm trả về là EOF giả dụ ghi tài liệu thất bại, trả về mã ASCII của kí trường đoản cú đượ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ở tệp tin my_document.txt trên Desktop lên đã thấy kí tự "A" đã làm được ghi vào, đồng thời trên console cũng in ra mã ASCII của kí trường đoản cú "A".

fputs:

int fputs(const char *str, tệp tin *f);Hàm fputs ghi một C-Style string vào tệp tin được trỏ mang đến bởi nhỏ trỏ f cho tới khi chạm mặt kí từ "".

Ví dụ:

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

Xem thêm: Yên Đổi Ra Tiền Việt Nam Jpy/Vnd, Chuyển Đổi Yên Nhật Sang Đồng Việt Nam Jpy/Vnd

Read data from file

Đầu tiên mình sẽ tạo một hàm khác có 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ẽ gọi hàm này sau thời điểm đã 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 chúng ta được mở để vừa đọc cùng ghi file, đề nghị mình sẽ thực hiện mode "w+" (hoặc "r+").

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 tài liệu văn bạn dạng từ file.

fgetc:

int fgetc(FILE *f);Hàm fgetc phát âm ra một kí tự vào file, internal file position indicator đã chuyển cho kí từ tiếp theo. Giá trị trả về là mã ASCII của kí tự vẫn đọ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 hiểu từ file ra (n - 1) kí tự, việc đọc dữ liệu có khả năng sẽ bị dừng nếu đọc được kí từ bỏ new line " " hoặc EOF. Chuỗi kí tự hiểu được vẫn lưu vào vùng lưu giữ được quản lý bởi con trỏ buf, nếu gọi dữ liệu thành công thì trả về add của buf, ngược 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ả gọi file được lưu vào mảng kí trường đoản cú str.

Reposition stream position indicator

Ghép những ví dụ làm việc trên lại, bọn họ có một chương trình đơn giản dễ dàng minh họa cho việc ghi file và đọc từng dòng dữ liệu (line by line) đã làm được ghi vào tệp tin 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 mở cửa this file" << std::endl;elsestd::cout << "File is opened" << std::endl;writeToFile(file);readFromFile(file);fclose(file);return 0;Tuy nhiên, kết quả cho ra màn hình không phải như mong muốn.

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

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

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

f là nhỏ trỏ trỏ đến đối tượng người sử dụng FILE đang mở.

offset là số bytes được cộng thêm tính từ địa chỉ origin.

origin là địa điểm đặt con trỏ vào file:

*

Như vậy, sau khi gọi hàm writeToFile xong, họ cần dịch rời internal tệp tin position indicator về đầu file bằng phương pháp như sau:

writeToFile(file);fseek(file, 0, SEEK_SET);readFromFile(file);Sau đó chạy lịch trình thì thấy tài liệu in ra màn hình đúng tựa như những gì chúng ta đã ghi vào file.

Determine kích thước of content of file

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

long int ftell(FILE *f);Hàm này đã trả về vị trí của file indicator đã trỏ cho trong file (số bytes của ngôn từ file cơ mà indicator đã chuẩn y qua).

Như vậy, các chúng ta cũng có thể đọc form size của câu chữ trong file bằng cách dịch internal tệp tin position indicator về vị trí sau cuối trong tệp tin rồi điện thoại tư vấn hàm ftell:

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

size_t fwrite(const void *ptr, size_t size, size_t count, file *f);Hàm fwrite dùng để làm ghi hàng bit trong vùng ghi nhớ được thống trị bởi bé trỏ ptr vào file đang rất được trỏ bởi f, size là số bytes đã copy từ vùng lưu giữ của ptr và count là số lần ghi vùng nhớ đó xuống file.

Hàm fwrite không niềm nở vùng ghi nhớ của chúng ta có định dạng gì, nó quan lại tâm form size vùng nhớ phải đọc và cứ nuốm copy tất cả các bits với file, mỗi lần sẽ copy 1 block of bit.

size_t fread(void *ptr, size_t size, size_t count, file *f);Hàm fread đang copy count lần block of bits có kích cỡ là size, đưa vào vùng nhớ được trỏ đến bởi ptr, từ file đã được thống trị bởi f.

Sau khi gọi hàm fread, internal file position indicator sẽ dịch rời tới (size * count) bytes từ bỏ vị trí bước đầ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 open 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 lịch trình trên đến ra tác dụng là rất nhiều kí từ bỏ rác.

Như chúng ta thấy, hàm fread đọc đúng 255 bytes vào file để mang vào vùng ghi nhớ của ptr nên các giá trị quá xuất hiện. Trong trường phù hợp này, cần sử dụng hàm fread và fwrite ko phù hợp. Hàm fread với fwrite thường xuyên được dùng để đọc cùng ghi dữ liệu kiểu struct vào file.

Write và read structs

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

Trước hết, mình sản xuất một struct đơn giản và 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 dữ liệu trong struct còn liên quan đến định nghĩa struct alignment). Vậy nên là mỗi unit có kiểu Employee được tạo ra đều chiếm một vùng nhớ có size 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ì size tên của mọi cá nhân sẽ khác nhau dẫn đến chúng ta không có một định dạng chung để dễ quản lý nhiều Employee vào file. Việc đặt nó vào trong 1 struct giúp bọn họ đọc cùng ghi file thuận lợi hơn nhiều.

Dưới đây là một đoạn chương trình chủng loại cho việc xử lý tệp tin để cai quản 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 chúng ta chạy demo đoạn lịch trình trên để thấy kết quả.

Bây giờ chúng ta cùng mở file my_document.txt trong thư mục Desktop để xem thử nội dung trong file như thế nào: