二进制序列化
C++ 支持以二进制模式读写文件,用于存储原始二进制数据(如结构体、图像、音频等)。
基本二进制读写
写入二进制
cpp
#include <fstream>
int num = 42;
double pi = 3.14159;
char c = 'A';
std::ofstream out("data.bin", std::ios::binary);
out.write(reinterpret_cast<const char*>(&num), sizeof(num));
out.write(reinterpret_cast<const char*>(&pi), sizeof(pi));
out.write(&c, sizeof(c));
out.close();读取二进制
cpp
#include <fstream>
int num;
double pi;
char c;
std::ifstream in("data.bin", std::ios::binary);
in.read(reinterpret_cast<char*>(&num), sizeof(num));
in.read(reinterpret_cast<char*>(&pi), sizeof(pi));
in.read(&c, sizeof(c));
in.close();结构体序列化
简单结构体
cpp
struct Person {
char name[20];
int age;
double salary;
};
// 写入
Person p = {"Alice", 30, 5000.0};
std::ofstream out("person.bin", std::ios::binary);
out.write(reinterpret_cast<const char*>(&p), sizeof(p));
out.close();
// 读取
Person readP;
std::ifstream in("person.bin", std::ios::binary);
in.read(reinterpret_cast<char*>(&readP), sizeof(readP));
in.close();带字符串的结构体(C++ 字符串)
cpp
#include <fstream>
#include <string>
struct Person {
std::string name; // 注意:二进制序列化 string 需要特殊处理
int age;
};
// 简单方式:逐字段序列化
void writePerson(std::ofstream& out, const Person& p) {
// 写入字符串长度
size_t len = p.name.size();
out.write(reinterpret_cast<const char*>(&len), sizeof(len));
// 写入字符串内容
out.write(p.name.c_str(), len);
// 写入其他字段
out.write(reinterpret_cast<const char*>(&p.age), sizeof(p.age));
}
Person readPerson(std::ifstream& in) {
Person p;
size_t len;
in.read(reinterpret_cast<char*>(&len), sizeof(len));
p.name.resize(len);
in.read(&p.name[0], len);
in.read(reinterpret_cast<char*>(&p.age), sizeof(p.age));
return p;
}字节序问题
不同系统可能使用不同的字节序(endianness),网络传输时需注意:
cpp
#include <cstdint>
// 大端字节序(网络序)
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
// 小端转大端
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);序列化最佳实践
使用 RAII 管理文件
cpp
#include <fstream>
#include <memory>
class BinaryFile {
public:
BinaryFile(const std::string& path, std::ios::mode mode) {
if (mode & std::ios::out) {
stream = std::make_unique<std::ofstream>(path, std::ios::binary);
} else {
stream = std::make_unique<std::ifstream>(path, std::ios::binary);
}
}
std::fstream& get() { return *stream; }
private:
std::unique_ptr<std::fstream> stream;
};
// 使用
{
BinaryFile out("data.bin", std::ios::out);
int x = 100;
out.get().write(reinterpret_cast<const char*>(&x), sizeof(x));
} // 自动关闭检查读写是否成功
cpp
std::ofstream out("data.bin", std::ios::binary);
int x = 42;
out.write(reinterpret_cast<const char*>(&x), sizeof(x));
if (!out) {
std::cerr << "写入失败!" << std::endl;
}
std::ifstream in("data.bin", std::ios::binary);
int y;
in.read(reinterpret_cast<char*>(&y), sizeof(y));
if (!in) {
std::cerr << "读取失败或数据不完整!" << std::endl;
}
// 检查实际读取的字节数
std::streamsize bytesRead = in.gcount();
std::cout << "实际读取了 " << bytesRead << " 字节" << std::endl;