Xử lý File trong C: Đọc ghi File văn bản và nhị phân

banner

Tóm tắt kiến thức

Xử lý file là kỹ năng thiết yếu để tạo ra các ứng dụng thực tế. Hiểu rõ cách đọc ghi file văn bản và nhị phân, quản lý file pointer và xử lý lỗi sẽ giúp bạn xây dựng các chương trình có thể lưu trữ và khôi phục dữ liệu.

Xử lý file là một phần quan trọng trong lập trình, cho phép lưu trữ và truy xuất dữ liệu một cách bền vững. Khả năng làm việc với file giúp tạo ra các ứng dụng thực tế có thể lưu trữ dữ liệu, cấu hình và trao đổi thông tin với các chương trình khác.

Quảng cáo giúp chúng tôi duy trì trang web này

Tổng quan về xử lý file

Khái niệm file

File là một tập hợp dữ liệu được lưu trữ trên thiết bị lưu trữ (ổ cứng, USB, v.v.). File cho phép dữ liệu tồn tại ngay cả khi chương trình kết thúc.

Các loại file

File văn bản (Text File): Chứa dữ liệu dạng văn bản, có thể đọc được bằng text editor

  • Dễ đọc và chỉnh sửa
  • Sử dụng ký tự newline để xuống dòng
  • Phù hợp cho cấu hình, log, dữ liệu người dùng

Mở và đóng file

Khai báo con trỏ file

FILE *con_trỏ_file;

Hàm fopen() - Mở file

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

Các chế độ mở file

ModeMô tả
"r"Mở để đọc (file phải tồn tại)
"w"Mở để ghi (tạo file mới hoặc ghi đè)
"a"Mở để ghi thêm vào cuối file
"r+"Mở để đọc và ghi
"w+"Tạo file mới để đọc và ghi
"a+"Mở để đọc và ghi thêm vào cuối

Ví dụ cơ bản:

#include <stdio.h>

int main() {
    FILE *file;

    // Mở file để ghi
    file = fopen("example.txt", "w");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    // Ghi dữ liệu vào file
    fprintf(file, "Xin chao, day la file vi du!\n");
    fprintf(file, "Chuong trinh C xu ly file.\n");

    // Đóng file
    fclose(file);

    printf("Da ghi file thanh cong!\n");

    return 0;
}

Ghi file văn bản

fprintf() - Ghi có định dạng

#include <stdio.h>

int main() {
    FILE *file = fopen("student.txt", "w");

    if (file == NULL) {
        printf("Khong the tao file!\n");
        return 1;
    }

    // Ghi thông tin sinh viên
    fprintf(file, "=== DANH SACH SINH VIEN ===\n");
    fprintf(file, "Ho ten: Nguyen Van A\n");
    fprintf(file, "Tuoi: %d\n", 20);
    fprintf(file, "Diem: %.2f\n", 8.5);
    fprintf(file, "Lop: %s\n", "CNTT01");

    fclose(file);
    printf("Da ghi thong tin sinh vien vao file!\n");

    return 0;
}

fputs() - Ghi chuỗi

#include <stdio.h>

int main() {
    FILE *file = fopen("lines.txt", "w");

    if (file == NULL) {
        printf("Khong the tao file!\n");
        return 1;
    }

    fputs("Dong thu nhat\n", file);
    fputs("Dong thu hai\n", file);
    fputs("Dong thu ba\n", file);

    fclose(file);
    printf("Da ghi cac dong vao file!\n");

    return 0;
}

fputc() - Ghi ký tự

#include <stdio.h>

int main() {
    FILE *file = fopen("characters.txt", "w");

    if (file == NULL) {
        printf("Khong the tao file!\n");
        return 1;
    }

    char ch = 'A';
    for (int i = 0; i < 26; i++) {
        fputc(ch + i, file);
        fputc(' ', file);
    }

    fclose(file);
    printf("Da ghi bang chu cai vao file!\n");

    return 0;
}

Đọc file văn bản

fscanf() - Đọc có định dạng

#include <stdio.h>

int main() {
    FILE *file = fopen("student.txt", "r");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    char name[50], class[20];
    int age;
    float grade;

    // Bỏ qua dòng tiêu đề
    char buffer[100];
    fgets(buffer, sizeof(buffer), file);

    // Đọc thông tin
    fscanf(file, "Ho ten: %[^\n]", name);
    fscanf(file, "Tuoi: %d", &age);
    fscanf(file, "Diem: %f", &grade);
    fscanf(file, "Lop: %s", class);

    printf("Thong tin sinh vien:\n");
    printf("Ho ten: %s\n", name);
    printf("Tuoi: %d\n", age);
    printf("Diem: %.2f\n", grade);
    printf("Lop: %s\n", class);

    fclose(file);

    return 0;
}

fgets() - Đọc dòng

#include <stdio.h>

int main() {
    FILE *file = fopen("lines.txt", "r");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    char line[100];

    printf("Noi dung file:\n");
    while (fgets(line, sizeof(line), file) != NULL) {
        printf("%s", line);
    }

    fclose(file);

    return 0;
}

fgetc() - Đọc ký tự

#include <stdio.h>

int main() {
    FILE *file = fopen("characters.txt", "r");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    char ch;
    printf("Noi dung file:\n");

    while ((ch = fgetc(file)) != EOF) {
        printf("%c", ch);
    }

    fclose(file);

    return 0;
}

Ghi file nhị phân

fwrite() - Ghi dữ liệu nhị phân

#include <stdio.h>

typedef struct {
    char name[50];
    int age;
    float salary;
} Employee;

int main() {
    Employee emp = {"Nguyen Van A", 30, 15000000};

    FILE *file = fopen("employee.bin", "wb");

    if (file == NULL) {
        printf("Khong the tao file!\n");
        return 1;
    }

    // Ghi struct vào file nhị phân
    fwrite(&emp, sizeof(Employee), 1, file);

    fclose(file);
    printf("Da ghi struct vao file nhi phan!\n");

    return 0;
}

Ghi mảng vào file nhị phân

#include <stdio.h>

int main() {
    int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int n = sizeof(numbers) / sizeof(numbers[0]);

    FILE *file = fopen("numbers.bin", "wb");

    if (file == NULL) {
        printf("Khong the tao file!\n");
        return 1;
    }

    // Ghi mảng vào file
    fwrite(numbers, sizeof(int), n, file);

    fclose(file);
    printf("Da ghi mang vao file nhi phan!\n");

    return 0;
}

Đọc file nhị phân

fread() - Đọc dữ liệu nhị phân

#include <stdio.h>

typedef struct {
    char name[50];
    int age;
    float salary;
} Employee;

int main() {
    Employee emp;

    FILE *file = fopen("employee.bin", "rb");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    // Đọc struct từ file nhị phân
    fread(&emp, sizeof(Employee), 1, file);

    printf("Thong tin nhan vien:\n");
    printf("Ten: %s\n", emp.name);
    printf("Tuoi: %d\n", emp.age);
    printf("Luong: %.0f\n", emp.salary);

    fclose(file);

    return 0;
}

Đọc mảng từ file nhị phân

#include <stdio.h>

int main() {
    int numbers[10];
    int n = 10;

    FILE *file = fopen("numbers.bin", "rb");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    // Đọc mảng từ file
    fread(numbers, sizeof(int), n, file);

    printf("Mang doc tu file:\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    fclose(file);

    return 0;
}

Di chuyển con trỏ file

fseek() - Di chuyển đến vị trí cụ thể

#include <stdio.h>

int main() {
    FILE *file = fopen("seek_example.txt", "w");

    if (file == NULL) {
        printf("Khong the tao file!\n");
        return 1;
    }

    // Ghi dữ liệu ban đầu
    fprintf(file, "1234567890");
    fclose(file);

    // Mở file để đọc
    file = fopen("seek_example.txt", "r");

    // Di chuyển đến vị trí thứ 5
    fseek(file, 5, SEEK_SET);

    char ch = fgetc(file);
    printf("Ky tu tai vi tri 5: %c\n", ch);

    // Di chuyển 2 vị trí từ vị trí hiện tại
    fseek(file, 2, SEEK_CUR);
    ch = fgetc(file);
    printf("Ky tu tai vi tri 7: %c\n", ch);

    // Di chuyển đến cuối file
    fseek(file, -1, SEEK_END);
    ch = fgetc(file);
    printf("Ky tu cuoi cung: %c\n", ch);

    fclose(file);

    return 0;
}

ftell() - Lấy vị trí hiện tại

#include <stdio.h>

int main() {
    FILE *file = fopen("seek_example.txt", "r");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    printf("Vi tri ban dau: %ld\n", ftell(file));

    fseek(file, 5, SEEK_SET);
    printf("Vi tri sau khi seek: %ld\n", ftell(file));

    char ch = fgetc(file);
    printf("Vi tri sau khi doc 1 ky tu: %ld\n", ftell(file));

    fclose(file);

    return 0;
}

rewind() - Về đầu file

#include <stdio.h>

int main() {
    FILE *file = fopen("seek_example.txt", "r");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    // Di chuyển đến giữa file
    fseek(file, 5, SEEK_SET);
    printf("Vi tri: %ld\n", ftell(file));

    // Về đầu file
    rewind(file);
    printf("Vi tri sau rewind: %ld\n", ftell(file));

    fclose(file);

    return 0;
}

Kiểm tra lỗi file

feof() - Kiểm tra cuối file

#include <stdio.h>

int main() {
    FILE *file = fopen("lines.txt", "r");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    char line[100];
    int lineCount = 0;

    while (!feof(file)) {
        if (fgets(line, sizeof(line), file) != NULL) {
            lineCount++;
            printf("Dong %d: %s", lineCount, line);
        }
    }

    printf("Tong so dong: %d\n", lineCount);

    fclose(file);

    return 0;
}

ferror() - Kiểm tra lỗi

#include <stdio.h>

int main() {
    FILE *file = fopen("nonexistent.txt", "r");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    char ch;
    while ((ch = fgetc(file)) != EOF) {
        printf("%c", ch);

        if (ferror(file)) {
            printf("Co loi khi doc file!\n");
            break;
        }
    }

    fclose(file);

    return 0;
}

Gộp nội dung file

#include <stdio.h>

int main() {
    FILE *file1, *file2, *merged;
    char ch;

    // Mở các file
    file1 = fopen("file1.txt", "r");
    file2 = fopen("file2.txt", "r");
    merged = fopen("merged.txt", "w");

    if (file1 == NULL || file2 == NULL || merged == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    // Gộp nội dung file1
    while ((ch = fgetc(file1)) != EOF) {
        fputc(ch, merged);
    }

    // Thêm nội dung file2
    while ((ch = fgetc(file2)) != EOF) {
        fputc(ch, merged);
    }

    fclose(file1);
    fclose(file2);
    fclose(merged);

    printf("Da gop noi dung 2 file thanh cong!\n");

    return 0;
}

Sao chép file

#include <stdio.h>

int main() {
    FILE *source, *destination;
    char ch;

    source = fopen("source.txt", "r");
    destination = fopen("copy.txt", "w");

    if (source == NULL || destination == NULL) {
        printf("Khong the mo file!\n");
        return 1;
    }

    while ((ch = fgetc(source)) != EOF) {
        fputc(ch, destination);
    }

    fclose(source);
    fclose(destination);

    printf("Da sao chep file thanh cong!\n");

    return 0;
}

Ví dụ thực hành

1. Quản lý danh sách sinh viên với file

#include <stdio.h>
#include <string.h>

typedef struct {
    int id;
    char name[50];
    float grade;
    int age;
} Student;

void saveStudents(Student students[], int n) {
    FILE *file = fopen("students.txt", "w");

    if (file == NULL) {
        printf("Khong the tao file!\n");
        return;
    }

    fprintf(file, "%d\n", n);
    for (int i = 0; i < n; i++) {
        fprintf(file, "%d %s %.2f %d\n",
                students[i].id, students[i].name,
                students[i].grade, students[i].age);
    }

    fclose(file);
    printf("Da luu danh sach sinh vien vao file!\n");
}

int loadStudents(Student students[]) {
    FILE *file = fopen("students.txt", "r");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 0;
    }

    int n;
    fscanf(file, "%d", &n);

    for (int i = 0; i < n; i++) {
        fscanf(file, "%d %s %f %d",
               &students[i].id, students[i].name,
               &students[i].grade, &students[i].age);
    }

    fclose(file);
    printf("Da tai danh sach sinh vien tu file!\n");

    return n;
}

void displayStudents(Student students[], int n) {
    printf("\n=== DANH SACH SINH VIEN ===\n");
    for (int i = 0; i < n; i++) {
        printf("ID: %d, Ten: %s, Diem: %.2f, Tuoi: %d\n",
               students[i].id, students[i].name,
               students[i].grade, students[i].age);
    }
}

int main() {
    Student students[100];
    int n = 0;
    int choice;

    do {
        printf("\n=== MENU ===\n");
        printf("1. Nhap sinh vien\n");
        printf("2. Hien thi danh sach\n");
        printf("3. Luu vao file\n");
        printf("4. Tai tu file\n");
        printf("5. Thoat\n");
        printf("Chon: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                if (n < 100) {
                    printf("Nhap thong tin sinh vien %d:\n", n + 1);
                    printf("ID: ");
                    scanf("%d", &students[n].id);
                    printf("Ten: ");
                    scanf(" %[^\n]", students[n].name);
                    printf("Diem: ");
                    scanf("%f", &students[n].grade);
                    printf("Tuoi: ");
                    scanf("%d", &students[n].age);
                    n++;
                } else {
                    printf("Danh sach da day!\n");
                }
                break;

            case 2:
                displayStudents(students, n);
                break;

            case 3:
                saveStudents(students, n);
                break;

            case 4:
                n = loadStudents(students);
                break;

            case 5:
                printf("Tam biet!\n");
                break;

            default:
                printf("Lua chon khong hop le!\n");
        }
    } while (choice != 5);

    return 0;
}

2. Ghi/đọc struct vào file nhị phân

#include <stdio.h>
#include <string.h>

typedef struct {
    char title[100];
    char author[50];
    int pages;
    float price;
} Book;

void saveBooks(Book books[], int n) {
    FILE *file = fopen("books.bin", "wb");

    if (file == NULL) {
        printf("Khong the tao file!\n");
        return;
    }

    // Ghi số lượng sách
    fwrite(&n, sizeof(int), 1, file);

    // Ghi danh sách sách
    fwrite(books, sizeof(Book), n, file);

    fclose(file);
    printf("Da luu %d quyen sach vao file nhi phan!\n", n);
}

int loadBooks(Book books[]) {
    FILE *file = fopen("books.bin", "rb");

    if (file == NULL) {
        printf("Khong the mo file!\n");
        return 0;
    }

    int n;
    fread(&n, sizeof(int), 1, file);
    fread(books, sizeof(Book), n, file);

    fclose(file);
    printf("Da tai %d quyen sach tu file nhi phan!\n", n);

    return n;
}

void displayBooks(Book books[], int n) {
    printf("\n=== DANH SACH SACH ===\n");
    for (int i = 0; i < n; i++) {
        printf("Ten sach: %s\n", books[i].title);
        printf("Tac gia: %s\n", books[i].author);
        printf("So trang: %d\n", books[i].pages);
        printf("Gia: %.0f VND\n", books[i].price);
        printf("--------------------\n");
    }
}

int main() {
    Book books[50];
    int n = 0;

    // Thêm một số sách mẫu
    strcpy(books[0].title, "Lap trinh C");
    strcpy(books[0].author, "Nguyen Van A");
    books[0].pages = 300;
    books[0].price = 150000;
    n++;

    strcpy(books[1].title, "Cau truc du lieu");
    strcpy(books[1].author, "Tran Thi B");
    books[1].pages = 400;
    books[1].price = 200000;
    n++;

    // Lưu vào file
    saveBooks(books, n);

    // Tải lại từ file
    Book loadedBooks[50];
    int loadedCount = loadBooks(loadedBooks);

    // Hiển thị
    displayBooks(loadedBooks, loadedCount);

    return 0;
}

Tổng kết

Xử lý file là kỹ năng thiết yếu để tạo ra các ứng dụng thực tế có thể lưu trữ và khôi phục dữ liệu.

Lưu ý quan trọng về xử lý file
  • Luôn đóng file: Sử dụng fclose() để tránh memory leak
  • Kiểm tra lỗi: Luôn kiểm tra kết quả fopen() trước khi sử dụng
  • File modes: Hiểu rõ sự khác biệt giữa "r", "w", "a"
  • Buffer flush: Sử dụng fflush() khi cần đảm bảo dữ liệu được ghi ngay
Best Practices
  • Luôn kiểm tra file pointer trước khi thao tác
  • Sử dụng binary mode cho dữ liệu struct
  • Kiểm tra EOF và lỗi khi đọc file
  • Sử dụng fseek() để di chuyển trong file hiệu quả
  • Backup dữ liệu quan trọng trước khi ghi đè

Với những kiến thức này, bạn đã sẵn sàng để xây dựng các ứng dụng có thể lưu trữ dữ liệu bền vững và tạo nền tảng cho các hệ thống quản lý dữ liệu phức tạp!

Last updated on