File nhị phân C++ | Code mẫu chi tiết

Đọc và ghi file là thao tác cơ bản trong lập trình C++ để quản lý dữ liệu như lưu trữ, cập nhật hoặc truy xuất thông tin từ file. Trong bài viết này, TTnguyen sẽ hướng dẫn cách thực hiện đọc và ghi file nhị phân c++ một cách khoa học và dễ hiểu.

Xem thêm:

1. Mô tả yêu cầu bài toán

Bài 39 (TH-CSLT-01). Viết chương trình bao gồm các chương trình con sau:

– Nhập một mảng số nguyên gồm n (n nhập từ bàn phím) phần tử.

– Lưu file (theo dạng nhị phân), nếu tệp chưa tồn tại thì tạo tệp mới, ngược lại, chèn toàn bộ mảng tệp.

– Đọc dữ liệu trong tệp ra một mảng số nguyên ra màn hình

–  Sắp xếp theo chiều giảm dần các giá trị trong A, lưu A vào tệp “A.dat”

+ Thực hiện tương tự như vậy và lưu vào tệp “B.dat” với mảng B gồm m phần tử.

+ Thực hiện đọc dữ liệu từ 02 tệp trên và ghép các dữ liệu đọc được vào tệp “C.dat”. Các dữ liệu trong tệp “C.dat” vẫn phải được đảm bảo theo trật tự giảm dần.

2. Lưu file nhị phân C++

Để lưu mảng số nguyên dưới dạng nhị phân, thực hiện như sau:

  • Khởi tạo đối tượng ofstream:
    • Sử dụng chế độ ios::binary để đảm bảo dữ liệu được ghi theo dạng nhị phân.
  • Ghi dữ liệu:
    • Ghi số phần tử của mảng.
    • Ghi toàn bộ giá trị mảng sử dụng phương thức write().
void luuFile(int a[], int n, string ten_tep) {
  ofstream ofs; //mo tep 
  ofs.open(ten_tep, ios::binary);
  //kiem tra 
  if (!ofs.is_open()) {
    cout << "Khong mo duoc tep!" << endl;
    return;
  }
  ofs.write((char * ) & n, sizeof(int)); // ghi n 
  ofs.write((char * ) & a[0], n * sizeof(int)); // ghi cac phan tu cua mang 
  ofs.close();
}

Giải thích:

  • Khởi tạo một đối tượng ofstream với tên ofs. Đối tượng này được sử dụng để ghi dữ liệu vào tệp tin. Hàm tiếp tục bằng việc mở tệp tin ten_tep với chế độ ios::binary, có nghĩa là tệp tin được mở để thực hiện các thao tác nhị phân.
  • Tiếp theo, hàm kiểm tra xem tệp tin đã được mở thành công hay chưa bằng cách sử dụng phương thức is_open() của đối tượng ofs. Nếu tệp tin không mở được, in ra thông báo lỗi và kết thúc hàm bằng câu lệnh return.
  • Nếu tệp tin mở thành công, hàm sẽ ghi số phần tử của mảng vào tệp tin bằng cách sử dụng phương thức write() của đối tượng ofs. Trước tiên, hàm chuyển đổi số nguyên n sang một con trỏ kiểu char bằng cách ép kiểu (char*)&n, sau đó ghi giá trị này vào tệp tin bằng phương thức write(). Đây là cách ghi dữ liệu nhị phân vào tệp tin.
  • Tiếp theo, ghi các phần tử của mảng a vào tệp tin bằng cách ép kiểu (char*)&a[0], và sử dụng kích thước mảng n nhân với kích thước của kiểu dữ liệu số nguyên để ghi toàn bộ mảng vào tệp tin.
  • Cuối cùng, hàm đóng tệp tin bằng phương thức close() của đối tượng ofs.

3. Đọc file nhị phân trong C++

Các bước thực hiện:

  • Khởi tạo ifstream: Mở file với chế độ nhị phân.
  • Đọc dữ liệu:
    • Đọc số phần tử từ file.
    • Đọc các giá trị mảng.
  • Đóng file sau khi đọc.
void docFile(int a[], int n, string ten_tep) {
  ifstream ifs;
  //mo file
  ifs.open(ten_tep, ios::binary);
  //kiem tra file
  if (!ifs.is_open()) {
    cout << "Khong mo duoc file!" << endl;
    return;
  }
  int read_n;
  ifs.read((char * ) & read_n, sizeof(int)); // doc so phan tu
  int read_numbers[read_n];
  ifs.read((char * ) & read_numbers, sizeof(int) * read_n); // doc cac phan tu

  // in cac phan tu ra man hinh
  for (int i = 0; i < read_n; i++) {
    cout << read_numbers[i] << " ";
  }
  cout << endl;
  ifs.close();
  cout << " Doc file thanh cong!" << endl;
}

Giải thích:

  • Khởi tạo một đối tượng ifstream với tên ifs để đọc dữ liệu từ tệp tin.
  • Tiếp theo, hàm kiểm tra xem tệp tin đã được mở thành công hay chưa bằng cách sử dụng phương thức is_open() của đối tượng ifs.
  • Nếu tệp tin mở thành công, hàm sẽ đọc số phần tử của mảng từ tệp tin bằng cách sử dụng phương thức read() của đối tượng ifs.
    • Đầu tiên, tạo một biến read_n để lưu số phần tử của mảng được đọc từ tệp tin. Hàm chuyển đổi số nguyên đó sang một con trỏ kiểu char bằng cách ép kiểu (char*)&read_n.
    • Sau đó sử dụng phương thức read() để đọc giá trị này từ tệp tin.
  • Tiếp theo, tạo một mảng read_numbers có kích thước bằng với read_n để lưu các phần tử của mảng được đọc từ tệp tin.
  • In các phần tử trong tệp ra màn hình.
  • Cuối cùng, sau khi đọc xong toàn bộ mảng từ tệp tin, hàm đóng tệp tin bằng phương thức close() của đối tượng ifs.

4. Kết hợp dữ liệu từ hai file nhị phân

– Hàm ghepFile_A_B() thực hiện các bước để ghép mảng trong hai tệp tin A.datB.dat thành một mảng mới và lưu vào tệp tin C.dat.

Để ghép dữ liệu từ hai file A.datB.dat vào file C.dat:

  1. Đọc dữ liệu từ cả hai file.
  2. Kết hợp mảng từ hai file.
  3. Sắp xếp mảng kết quả giảm dần.
  4. Ghi dữ liệu vào file C.dat

4.1. Mở tệp tin A.dat

– Trước hết, hàm mở tệp tin A.dat bằng đối tượng ifs và kiểm tra xem việc mở tệp có thành công hay không. Nếu không thành công thì hàm sẽ in ra thông báo và kết thúc. Sau đó, hàm đọc giá trị n đầu tiên từ tệp tin A.dat bằng phương thức read(), và sau đó đọc toàn bộ mảng readnumber_n gồm n phần tử từ tệp tin A.dat.

4.2. Mở tệp tin B.dat

– Tiếp theo, hàm mở tệp tin B.dat và kiểm tra việc mở tệp có thành công hay không. Nếu không thành công thì hàm sẽ in ra thông báo và kết thúc. Sau đó, hàm đọc giá trị m đầu tiên từ tệp tin B.dat bằng phương thức read(), và sau đó đọc toàn bộ mảng readnumber_m gồm m phần tử từ tệp tin B.dat.

4.3. Ghép 2 file

Sau khi đọc được hai mảng readnumber_nreadnumber_m, hàm tiến hành ghép chúng lại thành một mảng mới readnumber_n bằng cách duyệt qua từng phần tử của mảng readnumber_m và thêm chúng vào sau mảng readnumber_n.

Tiếp theo, hàm sắp xếp mảng readnumber_n theo thứ tự giảm dần bằng cách gọi hàm sapXep_giamdan(), sau đó lưu mảng readnumber_n vào tệp tin C.dat bằng cách gọi hàm luuFile(). Hàm tiếp tục in ra các phần tử của mảng readnumber_n sau khi đã ghép và sắp xếp xong, kết thúc bằng cách đóng tệp tin ifs.

5. Code mẫu hoàn chỉnh

#include <iostream>
#include <fstream>

using namespace std;

void nhap_mang(int a[], int &n) {

    cout << "Nhap so phan tu cua mang: ";
    cin >> n;

    for (int i = 0; i < n; i++) {
        cout << "Nhap phan tu thu " << i + 1 << ": ";
        cin >> a[i];
    }
}

void luuFile(int a[], int n, string ten_tep) {

    ofstream ofs;
    //mo tep
    ofs.open(ten_tep, ios::binary);
    //kiem tra
    if(!ofs.is_open()){
        cout<<"Khong mo duoc tep!"<<endl;
        return;
    }
    
    ofs.write((char*)&n, sizeof(int)); // ghi n
    ofs.write((char*)&a[0], n * sizeof(int)); // ghi cac phan tu cua mang
    ofs.close();
}

void docFile(int a[], int n, string ten_tep){

    ifstream ifs;
    //mo file
    ifs.open(ten_tep, ios::binary);
    //kiem tra file
    if(!ifs.is_open()){
        cout<<"Khong mo duoc file!"<<endl;
        return;
    }

    int read_n;

    ifs.read((char*)&read_n, sizeof(int)); // doc so phan tu

    int read_numbers[read_n];

    ifs.read((char*)&read_numbers, sizeof(int)*read_n);// doc cac phan tu
    
    // in cac phan tu ra man hinh
    for(int i=0;i<read_n;i++){
        cout<<read_numbers[i]<<" ";
    }
    cout<<endl;
    ifs.close();
    cout<<" Doc file thanh cong!"<<endl;
}

void xuat_mang(int a[], int n) {
    for (int i = 0; i < n; i++) {
        cout << a[i] << " ";
    }
    cout << endl;
}

void sapXep_giamdan(int a[], int n){

    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            if(a[i]<a[j]){
                int tg=a[i];
                a[i]=a[j];
                a[j]=tg;
            }
        }
    }
}

// Doc du lieu tu 2 tep A.dat va B.dat

void ghepFile_A_B(){

    ifstream ifs;
    // doc file A
    ifs.open("A.dat", ios::binary);

    if(!ifs.is_open()){
        cout<<"Khong mo duoc tep!"<<endl;
        return;
    }

    int read_n;
    ifs.read((char*)&read_n, sizeof(int));

    int readnumber_n[read_n];

    ifs.read((char*)&readnumber_n, read_n*sizeof(int));
    ifs.close();
    // doc file b

    ifs.open("B.dat", ios::binary);

    if(!ifs.is_open()){
        cout<<"Khong mo duoc tep!"<<endl;
        return;
    }

    int read_m;
    ifs.read((char*)&read_m, sizeof(int));

    int readnumber_m[read_m];

    ifs.read((char*)&readnumber_m, read_m*sizeof(int));


    //ghep mang
    for(int i=0;i<read_m;i++){
        readnumber_n[read_n+i]=readnumber_m[i];
    }
    // sap xep
    sapXep_giamdan(readnumber_n,read_m+read_n);

    //Luu file

    luuFile(readnumber_n,read_m+read_n,"C.dat");

    // Xuat mang
    cout<<" Mang C: ";
    for(int i=0;i<read_m+read_n;i++){
        cout<<readnumber_n[i]<<" ";
    }

    cout<<endl;
    ifs.close();

}

int main() {
    int chon;
    int a[255],n,b[255],m;

    do{
        cout<<" |1. Nhap mang A"<<endl;
        cout<<" |2. Nhap mang B"<<endl;
        cout<<" |3. Sap xep va luu file mang A"<<endl;
        cout<<" |4. Sap xep va luu file mang B"<<endl;
        cout<<" |5. Doc file mang A"<<endl;
        cout<<" |6. Doc file mang B"<<endl;
        cout<<" |7. Xuat mang C"<<endl;
        cout<<" |0. Thoat"<<endl;
        cout<<"Lua chon: "; cin>>chon;

        switch(chon){
            case 1: {
                nhap_mang(a,n);
                cout<<" Mang A: ";
                xuat_mang(a,n);
                break;
            }
            case 2: {
                nhap_mang(b,m);
                cout<<" Mang B: ";
                xuat_mang(b,m);
                break;
            }
            case 3: {
                sapXep_giamdan(a,n);
                luuFile(a,n, "A.dat");
                break;
            }
            case 4: {
                sapXep_giamdan(b,m);
                luuFile(b,m, "B.dat");
                break;
            }
            case 5: {
                docFile(a,n,"A.dat");
                break;
            }
            case 6: {
                docFile(b,m,"B.dat");
                break;
            }
            case 7: {
                // gop mang
                ghepFile_A_B();

                break;
            }

            default :break;

        }

    }while(chon!=0);

    return 0;
}

4. Kết quả chạy chương trình

Lưu file, đọc file dạng nhị phân c++

 

 

 

 

 

 

 

 

 

 

 

 

Trên đây là đoạn mã đọc ghi file binary trong c. Cảm ơn các bạn đã tham khảo!

Tải full bài tập thực hành lập trình C/C++ có lời giải:

Bài viết cùng chủ đề:

thuật toán prim

tách mảng c++

viết chương trình tính chỉ số bmi c

Nguyễn Tiến Trường

Mình viết về những điều nhỏ nhặt trong cuộc sống, Viết về câu chuyện những ngày không có em