數據持久化是程序的核心能力。對於未接觸數據庫的開發者,文件 I/O 是最直接的入門路徑。本文從 C++ 文件流基礎出發,對比文本/二進制模式,演示手工解析的局限,最後引入 nlohmann/json 庫實現結構化存儲,兼顧簡潔與擴展性。
std::ifstream:輸入(讀)std::ofstream:輸出(寫)std::fstream:雙向均定義於 <fstream>,繼承自 iostream 體系,支持 << >> get() getline() read() write() 等操作。
| 標誌 | 含義 |
|---|---|
ios::in | 讀模式打開 |
ios::out | 寫模式打開(默認截斷文件) |
ios::app | 追加模式(寫入定位到末尾) |
ios::ate | 打開後定位到末尾(可隨後移動) |
ios::binary | 二進制模式(無換行符轉換) |
ios::trunc | 截斷現有文件(out 默認帶此標誌) |
std::fstream file("data.bin", std::ios::in | std::ios::out | std::ios::binary);
if (!file.is_open()) { /* 錯誤處理 */ }
int 20000 輸出為 5 字節 "20000",Windows 下 \n ↔ \r\n 轉換。適合人類閱讀、跨平台交換。int 佔 4 字節,無轉換。體積小、讀寫快、適合結構體/類序列化,但不可直接文本編輯。
// 寫入
std::fstream f("sprites.txt", std::ios::app);
f << profession << ' ' << weapon << '\n';
// 讀取
std::fstream f("sprites.txt", std::ios::in);
while (f >> profession >> weapon) { /* 構造對象 */ }
痛點:
JSON 本質是字符串,天然適合文件存儲。推薦 nlohmann/json(單頭文件、C++11、MIT 許可證、星標 40k+)。
#include
using json = nlohmann::json;
// 序列化
json j;
j["profession"] = "Mage";
j["weapon"] = "truncheon";
j["level"] = 10;
std::string s = j.dump(4); // 美化縮進 4 空格
// 反序列化
json j2 = json::parse(s);
std::string prof = j2["profession"]; // 自動類型轉換
int lvl = j2.value("level", 1); // 帶默認值的安全訪問
// 容器直接轉換
std::vector vec = {1,2,3};
json jvec = vec; // [1,2,3]
auto vec2 = jvec.get>();
#include
#include
#include
#include
using json = nlohmann::json;
class Sprite {
public:
std::string profession, weapon;
Sprite(std::string p="", std::string w="") : profession(p), weapon(w) {}
// 可選:提供 to_json/from_json 友元實現自動轉換
};
// 保存向量
bool saveSprites(const std::string& path, const std::vector>& sprites) {
json j = json::array();
for (auto& sp : sprites) {
j.push_back({{"profession", sp->profession}, {"weapon", sp->weapon}});
}
std::ofstream f(path);
if (!f) return false;
f << j.dump(4);
return true;
}
// 載入向量
bool loadSprites(const std::string& path, std::vector>& sprites) {
std::ifstream f(path);
if (!f) return false;
json j = json::parse(f);
for (auto& item : j) {
sprites.emplace_back(std::make_shared(
item["profession"].get(),
item["weapon"].get()
));
}
return true;
}
value() / contains())若數據量極大(GB 級)或極度敏感延遲,可考慮:
.proto 編譯但對 95% 的應用場景,JSON + nlohmann/json 已足夠**,開發效率與性能平衡最佳。
從 fstream 手工拼接到 nlohmann/json 一鍵序列化,核心思想是「用標準化格式隔離業務邏輯與存儲細節」。初學者先掌握文件流基礎,再引入 JSON 庫,即可在無數據庫環境下構建健壯的持久化層,為未來遷移到 SQLite/Redis/MySQL 打下良好基礎。