在C語言開發中,當需要存儲少量結構化數據時,引入MySQL等重型數據庫顯得過於繁瑣。更輕量的方案是將結構體數據直接以二進制形式寫入文件,需要時再讀取還原。本文通過完整的代碼示例,演示如何實現結構體的文件讀寫操作,並封裝為可復用的函數庫。
我們定義兩個核心函數:writeStruct 用於將內存中的結構體數據寫入文件,readStruct 用於從文件讀取數據還原到內存。兩者均採用緩衝區指針配合長度參數的方式,可適配任意結構體類型。
#ifndef STRUCT_H
#define STRUCT_H
#include <stdbool.h>
/**
* 將結構體數據寫入文件
* @param fileName 文件名
* @param buffer 數據緩衝區指針
* @param bufferLen 緩衝區長度(字節)
* @param mode 文件打開模式(如 "wb")
* @return 成功返回 true,失敗返回 false
*/
bool writeStruct(const char *fileName, const void *buffer, size_t bufferLen, const char *mode);
/**
* 從文件讀取數據到結構體
* @param fileName 文件名
* @param buffer 接收緩衝區指針
* @param bufferLen 緩衝區長度(字節)
* @param mode 文件打開模式(如 "rb")
* @return 成功返回 true,失敗返回 false
*/
bool readStruct(const char *fileName, void *buffer, size_t bufferLen, const char *mode);
#endif
#include "struct.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool writeStruct(const char *fileName, const void *buffer, size_t bufferLen, const char *mode) {
FILE *fp = fopen(fileName, mode);
if (!fp) {
perror("fopen");
return false;
}
// 確保從文件開頭寫入
rewind(fp);
size_t written = fwrite(buffer, 1, bufferLen, fp);
if (written != bufferLen) {
perror("fwrite");
fclose(fp);
return false;
}
fclose(fp);
return true;
}
bool readStruct(const char *fileName, void *buffer, size_t bufferLen, const char *mode) {
FILE *fp = fopen(fileName, mode);
if (!fp) {
perror("fopen");
return false;
}
rewind(fp);
// 讀取前清零緩衝區,避免殘留數據
memset(buffer, 0, bufferLen);
size_t readCount = fread(buffer, 1, bufferLen, fp);
if (readCount != bufferLen) {
// 讀取長度不足可能是文件損壞或結構不匹配
perror("fread");
fclose(fp);
return false;
}
fclose(fp);
return true;
}
以下示例演示如何將一個學生信息結構體保存到文件並讀回:
#include "struct.h"
#include <stdio.h>
typedef struct {
int id;
char name[32];
float score;
} Student;
int main() {
Student stu = {1001, "張三", 92.5f};
const char *filename = "student.dat";
// 寫入文件
if (writeStruct(filename, &stu, sizeof(Student), "wb")) {
printf("數據寫入成功。\n");
} else {
printf("寫入失敗。\n");
return 1;
}
// 讀取文件
Student readStu = {0};
if (readStruct(filename, &readStu, sizeof(Student), "rb")) {
printf("讀取成功:ID=%d, 姓名=%s, 分數=%.1f\n",
readStu.id, readStu.name, readStu.score);
} else {
printf("讀取失敗。\n");
}
return 0;
}
"wb" 和 "rb" 避免文本模式下的換行符轉換,確保數據位級一致。sizeof(結構體),否則會導致讀寫越界或數據截斷。#pragma pack)。perror 輸出系統錯誤信息,便於調試。通過封裝 fwrite/fread 並統一錯誤處理流程,我們獲得了一套簡潔、可復用的結構體持久化方案。這對於配置文件、遊戲存檔、嵌入式設備參數保存等場景極具實用價值。