[C/C++] Tập tin trong ngôn ngữ lập trình C

      Trong ngôn ngữ lập trình C thì tập tin cũng là một chương kiến thức cần thiết dành cho các bạn. Khi bạn học lập trình C, C++ nói riêng và các ngôn ngữ lập trình khác nói chung, đều mong muốn của các bạn là sau khi chương trình thực hiện được các yêu cầu thì cần phải lưu lại dữ liệu. Hay nói cách khác là cần có cơ sở dữ liệu để có thể truy xuất vào bất kỳ khi nào mong muốn.

       Tuy nhiên nếu bạn chỉ sử dụng những kiến thức thông thường thì dữ liệu của bạn sẽ lưu tạm trên RAM và thường bị mất đi sau khi bạn đóng chương trình. Như vậy cứ mỗi lần sử dụng bạn đều phải nhập lại dữ liệu -> Điều này là chưa hoàn thiện.

      Như vậy ý nghĩa cơ bản nhất mà tập tin đem lại cho các bạn là sử dụng để lưu trữ các dữ liệu, hay nói cách khác là tạo cơ sở dữ liệu cho các bạn. Cơ sở dữ liệu này được lưu trữ trực tiếp lên hệ điều hành của máy tính, khi nào cần thiết thì các bạn có thể dùng lệnh để đọc hoặc ghi thêm nội dung cho tập tin đó.

      Phân loại tập tin lưu trữ:

      Trong ngôn ngữ C dữ liệu được lưu trữ thông qua 2 dạng là tập tin ký tự ( tập tin văn bản) và tập tin nhị phân ( tập tin mã hóa).

   – Tập tin văn bản: là dạng tập tin lưu bằng những ký tự văn bản, các bạn có thể sử dụng các chương trình đọc văn bản như notepad, microsoft word để đọc được tập tin trên hệ điều hành.

   – Tập tin nhị phân: là những tập tin sẽ được mã hóa và nếu các bạn có sử dụng những chương trình đọc văn bản thì chỉ thấy được những ký tự đặc biệt, không phải là những ký tự thông thường.

      Đối với mỗi dạng tập tin thì sẽ có một số lệnh thao tác dành riêng cho tập tin đó, nên các bạn muốn sử dụng tập tin nào thì phải biết những tập lệnh để thực hiện các thao tác cho phù hợp.

     Tuy nhiên, cho dù tập tin theo dạng văn bản hay dạng nhị phân thì đều phải thực hiện qua 4 bước sau:

  • Bước 1: Khai báo con trỏ dạng tập tin
  • Bước 2: Mở tập tin theo các Mode mong muốn
  • Bước 3: Xử lý tập tin bằng tập lệnh riêng
  • Bước 4: Đóng tập tin

   Tiếp theo chúng ta tiến hành khảo sát các bước trên một cách chi tiết như sau:

     * * Phần 1: Khai báo con trỏ dạng tập tin

     Vì tập tin nằm trên hệ điều hành nên không thể sử dụng những lệnh thông thường để truy xuất, do vậy chúng ta cần khai báo con trỏ để trỏ đến tập tin trên hệ điều hành.

     Cú pháp để thực hiện khai báo này:

           FILE  *<Tên con trỏ>;

          Ví dụ: FILE *f;

        = > Sau khi khai báo xong thì chương trình sẽ tạo ra một con trỏ f, con trỏ này có chức năng trỏ đến một tập tin.

     Lưu ý: trong cú pháp khai báo thì từ khóa FILE phải viết bằng chữ in hoa.

     * * Phần 2: Mở tập tin theo các Mode mong muốn

     Về cơ bản thì các bạn có 2 mode lựa chọn thao tác lên tập tin, đó là mở tập tin để đọc hay để ghi nội dung cho tập tin đó.

    Cú pháp:    fopen(<đường dẫn tập tin>, <mode>);

          Ví dụ: fopen(“D:\\Docso.txt”,”wt”);

          – Đường dẫn tập tin: có thể là một đường dẫn cấp 1 để chỉ cho chương trình biết tập tin đang ở đâu trong máy tính, hoặc có thể là tên một tập tin nếu như tập tin đó nằm chung đường dẫn với nơi chứa code của chương trình.

          – Mode: Cơ bản chúng ta sẽ có các mode sau

  • t: là kiểu truy cập tập tin dạng văn bản (text)
  • b: là kiểu truy cập tập tin dạng nhị phân (binary)
  • r: mở tập tin đã tồn tại với mục đích đọc (read only).
  • w: mở tập tin để ghi vào (create/ write), nếu chưa có tập tin thì chương trình sẽ tạo tập tin mới.
  • a: mở tập tin để thêm vào cuối (append), nếu tập tin chưa tồn tại thì chương trình sẽ tạo tập tin mới.
  •  r+: mở tập tin với mục đích đọc và ghi.
  •  w+: mở tập tin với mục đích đọc và ghi, sẽ làm trắng tập tin đã tồn tại nếu tập tin này có và tạo tập tin mới nếu chưa có.
  •  a+: mở tập tin đã tồn tại với mục đích đọc và ghi. Nó tạo tập tin mới nếu chưa tồn tại. Việc đọc sẽ bắt đầu từ đầu, nhưng ghi sẽ chỉ cho phép ghi vào cuối.

 * * Phần 3a: Các lệnh thao tác trên tập tin văn bản

      a.  Lệnh đọc tập tin kiểu văn bản

  • Lệnh fscanf(<tên con trỏ tập tin>,<mặt nạ dữ liệu>,&<biến>);

    • Chức năng: Đọc dữ liệu từ tập tin văn bản, lấy dữ liệu từ tập tin gán cho biến x. Lệnh sẽ được đọc dữ liệu đến khi gặp khoảng trắng đầu tiên thì kết thúc. Lệnh này không sử dụng đọc cho kiểu dữ liệu char.
    • Ví dụ: fscanf(f,”%d”,&x);
      • => Biến x sẽ nhận những giá trị kiểu int đọc được từ tập tin.

  • Lệnh fgets(<tên chuỗi nhận>,<kích thước tối đa của chuỗi>, <tên con trỏ tập tin>);

    • Chức năng: Đọc một chuỗi ký tự từ tập tin theo kích thước tối đa trên lệnh hoặc khi xuống dòng (\n). Sử dụng được cho tất cả các kiểu dữ liệu.
    • Ví dụ: char ch[100];
      •       fgets(ch,100,f);

      • => lệnh sẽ tiến hành đọc tối đa 100 ký tự có trong tập tin và chuỗi ch[100] sẽ lưu trữ giá trị đọc được đó.

  • Lệnh getc(<con trỏ tập tin>);

    • Chức năng: Đọc từng ký tự của tập tin, ký tự này có thể mang kiểu char hoặc int. Muốn đọc hết tập tin bạn cần phải sử dụng thêm vòng lặp.
    • Ví dụ: char kt;
      • kt=getc(f);

      • => lệnh này sẽ đọc 1 ký tự từ tập tin.

     b.  Lệnh ghi tập tin kiểu văn bản

  • Lệnh fprintf(<con trỏ tập tin>,<mặt nạ dữ liệu>[,<tên biến ghi>]);

    • Chức năng: Ghi dữ liệu từ biến đưa vào tập tin. Biến này có thể là char hoặc int.
    • Ví dụ 1: int x=15;
      • fprintf(f,”%d”,x);

      • => Ghi dữ liệu từ biến x vào cho tập tin.

    • Ví dụ 2: fprintf(f,”Noi dung ghi vao tap tin…\n”);

      • => Nếu không sử dụng đối số thứ 3, thì có thể nhập nội dung cần ghi lên trên lệnh.

    • Một số trường hợp riêng biệt được sử dụng thêm cho lệnh fprintf

      • fprintf(f,”%[^EOF]”,x); => Ghi toàn bộ dữ liệu từ chuỗi x vào tập tin, EOF là ký hiệu kết thúc tập tin.

      • fprintf(f,”%[^\n]”,x); => Ghi 1 dòng dữ liệu từ chuỗi x vào tập tin, \n là ký tự xuống dòng.

  • Lệnh fputs(<chuỗi ký tự>,<con trỏ tập tin>);

    • Chức năng: Ghi một chuỗi ký tự vào tập tin.
    • Ví dụ: fputs(“Chuoi ky tu can ghi”,f);
      • => Ghi nội dung từ lệnh vào trong tập tin.

  • Lệnh fputc(<biến kiểu int>, <con trỏ tập tin>);

    • Chức năng: Ghi từng ký tự kiểu int vào tập tin.
    • Ví dụ: int b=16;
      • fputc(b,f);

      • => Ghi số 16 vào tập tin.

 * * Phần 3b: Các lệnh thao tác trên tập tin nhị phân

      a.  Lệnh đọc tập tin kiểu nhị phân

  • Lệnh fread(<vùng nhớ nhận dữ liệu>,<Kích thước của mỗi ô nhớ nhận>,<độ dài cần đọc>,<con trỏ tập tin>);

    • Chức năng: Đọc dữ liệu của 1 tập tin và đưa vào vùng nhớ nhận dữ liệu, vùng nhớ này có thể là mảng/ chuỗi hoặc có thể là biến. Nếu là biến thì cần có ký hiệu & đứng trước vùng nhớ đó.

    • Ví dụ: int A[50], B, n;

      • fread(A, sizeof(int), n, f);  => Đọc và gán toàn bộ giá trị cho 1 mảng A.

      • fread(&B, sizeof(int),1,f); => Đọc 1 giá trị và gán giá trị đó cho biến B.

      b.  Lệnh ghi tập tin kiểu nhị phân

  • Lệnh fwrite(<vùng nhớ ghi dữ liệu>,<Kích thước của mỗi ô nhớ ghi>,<độ dài cần đọc>,<con trỏ tập tin>);

    • Chức năng: ngược lại với hàm fread. Hàm này ghi toàn bộ dữ liệu có trong vùng nhớ ghi dữ liệu cho tập tin.
    • Ví dụ: int A[50], n;
      • fwrite(A,sizeof(int),n,f); => Ghi dữ liệu từ mảng A vào tập tin.

* * Phần 4: Đóng tập tin sau khi thao tác

     Sau khi không còn làm việc với tập tin nữa, chúng ta nên tiến hành đóng tập tin lại nhằm mục đích bảo đảm an toàn cho tập tin.

     Cú pháp: fclose(<con trỏ tập tin>); // Đóng tập tin có biến con trỏ làm đối số

     hoặc: fcloseall();  // Đóng toàn bộ tập tin đang mở

Ví dụ: FILE *f;

fclose(f);

* * Phần 5: Một số hàm sử dụng để thao tác trên tập tin

  • Hàm remove(<đường dẫn tập tin>);

    • Chức năng: hàm này được sử dụng để xóa tập tin.
    • Ví dụ: remove(“D:\\Docso.txt”);
  • Hàm rename(<tên cũ>, <tên mới>);

    • Chức năng: được sử dụng để đổi tên cho tập tin
    • Ví dụ: rename(“Docso.txt”,”Baitap.txt”);
  • Hàm fseek(<con trỏ tập tin>,<độ dời>,<mốc>);

    • Chức năng: dùng để di chuyển con nháy trong tập tin
    • Mốc là vị trí đầu tiên để tính khoảng cách cho độ dời, một số mốc là:
      • SEEK_SET vị trí mốc là đầu tập tin ( giá trị 0)
      • SEEK_CUR vị trí mốc là vị trí hiện hành của con trỏ ( giá trị 1)
      • SEEK_END vị trí mốc là cuối tập tin ( giá trị 2)
      • Ví dụ: Dời con trỏ về phải 3 byte bắt đầu từ vị trí đầu tiên, sử dụng lệnh fseek(f,+3,0) hoặc fseek(f,+3,SEEK_SET)
  • Hàm ftell(<con trỏ tập tin>);

    • Chức năng: Hàm cho biết vị trí con trỏ trong tập tin, vị trí là số byte tính từ đầu tập tin đến vị trí con trỏ.
    • Ví dụ: int size;
      • size = ftell(f);
      • => size: là khoảng cách từ đầu tập tin đến vị trí hiện hành của con trỏ
  • Hàm int feof(<con trỏ tập tin>);

    • Chức năng: hàm kiểm tra cuối tập tin hay chưa. Nếu kết quả bằng 0 thì chưa cuối tập tin. Nếu khác 0 thì đã cuối tập tin.
  • Hàm rewind(<con trỏ tập tin>);

    • Chức năng: Chuyển con trỏ về vị trí đầu tiên của tập tin.

* * Phần 6: Ví dụ

       Chương trình nhập vào 1 chuỗi, ghi chuỗi đó vào tập tin và đọc chuỗi đó từ tập tin lên màn hình.

#include<conio.h>
#include<stdio.h>

int main()
{
	char CH[100], c;
	int n;
	printf("Nhap vao chuoi can ghi: ");
	gets(CH);

	FILE *f;
	f= fopen("C:\\Tep.txt","wt");
	if(f==NULL)
		printf("\nKhong mo duoc tap tin Tep.txt\n");
	else
	{
		fputs(CH,f); //Cach 2 - dung de ghi
		printf("Da ghi noi dung thanh cong\n");
		fclose(f);
	}

	f=fopen("C:\\Tep.txt","rt");
	if(f==NULL)
	        printf("\nKhong mo duoc tap tin Tep.txt\n");
        else
         {	
	fscanf(f,"^[EOF]",CH);
	printf("%s",CH);		

        printf("\nDa doc noi dung thanh cong\n");
        fclose(f);
         }
	getch();
}

 


Categories:

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *