Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Ghi file nhị phân (Binary File) trong C++

Để ghi file nhị phân trong C++, dùng phương thức write() của std::ofstream. Ghi khối byte từ bộ nhớ ra file, bắt đầu tại con trỏ "put".

Cú pháp

ostream& write(const char* buffer, std::streamsize count);

Thuật toán

Bắt đầu
    Định nghĩa struct Student { int roll_no; string name; };
    Mở file "student.dat" ở chế độ ios::out | ios::binary
    Kiểm tra mở thành công
    Khởi tạo mảng 3 Student
    Với mỗi student: write((char*)&student, sizeof(Student))
    Đóng file
    Kiểm tra lỗi ghi (good())
    In dữ liệu đã ghi ra màn hình
Kết thúc

Mã nguồn

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

struct Student {
    int roll_no;
    string name; // ⚠️ string chứa con trỏ – KHÔNG an toàn ghi nhị phân trực tiếp!
};

int main() {
    ofstream wf("student.dat", ios::out | ios::binary);
    if (!wf) { cout << "Cannot open file!" << endl; return 1; }

    Student wstu[3] = { {1, "Ram"}, {2, "Shyam"}, {3, "Madhu"} };

    for (int i = 0; i < 3; i++)
        wf.write(reinterpret_cast<char*>(&wstu[i]), sizeof(Student));

    wf.close();
    if (!wf.good()) { cout << "Error occurred at writing time!" << endl; return 1; }

    cout << "Student's Details:" << endl;
    for (int i = 0; i < 3; i++) {
        cout << "Roll No: " << wstu[i].roll_no << endl;
        cout << "Name: " << wstu[i].name << endl << endl;
    }
    return 0;
}

Kết quả

Student's Details:
Roll No: 1
Name: Ram

Roll No: 2
Name: Shyam

Roll No: 3
Name: Madhu

⚠️ Vấn đề nghiêm trọng: std::string trong struct

std::string quản lý bộ nhớ động (con trỏ trỏ đến heap). Ghi sizeof(Student) chỉ ghi bản sao con trỏ, không ghi nội dung chuỗi. Khi đọc lại, con trỏ trỏ sai → crash hoặc dữ liệu rác.

Cách đúng: Chuỗi ký tự cố định hoặc serialize

// Cách 1: Mảng char cố định (POD - Plain Old Data)
struct Student {
    int roll_no;
    char name[32]; // kích thước cố định
};

// Cách 2: Serialize thủ công (ghi độ dài + dữ liệu)
void writeString(ofstream& ofs, const string& s) {
    uint32_t len = s.size();
    ofs.write(reinterpret_cast<char*>(&len), sizeof(len));
    ofs.write(s.data(), len);
}
void readString(ifstream& ifs, string& s) {
    uint32_t len;
    ifs.read(reinterpret_cast<char*>(&len), sizeof(len));
    s.resize(len);
    ifs.read(&s[0], len);
}

Lưu ý thêm

  • File nhị phân phụ thuộc kiến trúc (endianness, kích thước kiểu, padding struct). Không portable giữa nền tảng.
  • Dùng #pragma pack hoặc alignas để kiểm soát padding nếu cần.
  • Thư viện serialization: Boost.Serialization, cereal, protobuf, msgpack.