C++写文件笔记
C++二进制文件写入
二进制文件写入是C++高频操作,相比文本文件,具有体积小、读写快、数据完整的优势,适用于序列化、配置保存等场景。以下为两种核心写入方式(C语言风格、C++原生风格),主目录仅保留最简示例,进阶操作(如指针定位)放在对应子章节,便于分层学习。
1. C语言风格FILE*写入(兼容适配首选)
1.1 FILE*基础:写文件
适配C/C++混合、嵌入式、老项目,依赖<cstdio>,需手动管理文件指针,主目录仅展示"打开-写入-关闭"最简流程。
cpp
#include <cstdio>
using namespace std;
struct Student { char name[20]; int age; float score; };
int main() {
// 1. 打开二进制文件(wb=二进制写入,不存在则创建,存在则覆盖)
FILE* fp = fopen("test_fwrite.bin", "wb");
if (!fp) return 1; // 校验打开结果
// 2. 最简写入:基础数据+自定义结构体
int num = 123456;
Student stu = {"ZhangSan", 20, 95.5f};
fwrite(&num, sizeof(int), 1, fp);
fwrite(&stu, sizeof(stu), 1, fp);
// 3. 关闭文件,释放资源
fclose(fp);
return 0;
}
所用核心函数原型及参数解释(最简版)
- fopen :
FILE* fopen(const char* filename, const char* mode);,参数:文件路径、打开模式("wb"=二进制写入)。 - fwrite :
size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream);,参数:数据地址、单个元素字节数、元素个数、文件指针。 - fclose :
int fclose(FILE* stream);,参数:文件指针,功能:释放资源。
1.2 FILE*进阶:文件指针定位(fseek用法)
在最简写入基础上,新增fseek指针定位功能,实现指定位置写入/覆盖,适用于灵活调整写入位置的场景。
>using namespace std;
int main() {
FILE* fp = fopen("test_fwrite_seek.bin", "wb");
if (!fp) return 1;
int num1 = 123456, num2 = 654321;
// 先写入num1,指针自动移动到文件末尾
fwrite(&num1, sizeof(int), 1, fp);
// 定位指针到文件开头(SEEK_SET=文件起始),覆盖写入num2
fseek(fp, 0, SEEK_SET);
fwrite(&num2, sizeof(int), 1, fp);
// 定位指针到当前位置(SEEK_CUR),向后偏移4字节,写入新数据
fseek(fp, 4, SEEK_CUR);
int num3 = 7890;
fwrite(&num3, sizeof(int), 1, fp);
fclose(fp);
return 0;
}
进阶函数(fseek)原型及参数解释
- fseek :
int fseek(FILE* stream, long int offset, int origin);
参数1(stream):文件指针;
参数2(offset):偏移量(正数向后移,负数向前移);
参数3(origin):偏移基准(SEEK_SET=文件起始、SEEK_CUR=当前位置、SEEK_END=文件末尾)。
2. 标准ofstream流写入(C++原生首选)
2.1 ofstream基础:写文件
纯C++环境、跨平台首选`,ofstream类封装,无需手动管理指针,主目录仅展示"打开-写入-关闭"最简流程。
cpp
#include<fstream>
using namespace std;
struct Student { char name[20]; int age; float score; };
int main() {
// 1. 打开二进制文件(ios::binary=二进制,ios::out=写入)
ofstream ofs("test_fstream.bin", ios::binary | ios::out);
if (!ofs.is_open()) return 1; // 校验打开结果
// 2. 最简写入:基础数据+自定义结构体
int num = 123456;
Student stu = {"LiSi", 21, 92.0f};
ofs.write((char*)&num, sizeof(num));
ofs.write((char*)&stu, sizeof(stu));
// 3. 关闭文件流
ofs.close();
return 0;
}
所用核心方法原型及参数解释(最简版)
- ofstream 构造函数 :
ofstream(const char* filename, ios_base::openmode mode);,参数:文件路径、打开模式。 - ofstream::is_open :
bool is_open() const;,返回值:true=打开成功。 - ofstream::write :
ostream& write(const char* ptr, streamsize count);,参数:数据地址(强转char*)、写入字节数。 - ofstream::close :
void close();,功能:释放文件资源。
2.2 ofstream底层流进阶:指针定位与灵活写入
依托ostream基类特性,在ofstream最简写入基础上,新增seekp指针定位、分块写入等进阶操作,体现灵活性与可扩展性。
cpp
>using namespace std;
int main() {
ofstream ofs("test_ostream_advance.bin", ios::binary | ios::out);
if (!ofs) return 1;
// 1. 零散数据拼接写入
char header[] = "BIN_FILE";
int count = 3;
float a = 10.5f, b = 20.8f, c = 30.2f;
ofs.write(header, sizeof(header));
ofs.write((char*)&count, sizeof(count));
ofs.write((char*)&a, sizeof(a));
// 2. seekp指针定位:定位到文件开头,覆盖写入数据总大小
ofs.seekp(0, ios::beg);
int total_size = sizeof(header) + sizeof(count) + sizeof(a) + sizeof(b) + sizeof(c);
ofs.write((char*)&total_size, sizeof(total_size));
// 3. 大文件分块写入(避免占用过多内存)
const int BUF_SIZE = 1024;
char big_data[1024 * 10];
for (int i = < 1024*10; i++) big_data[i] = i % 256;
int pos = 0, total = sizeof(big_data);
while (pos < total) {
int write_size = min(BUF_SIZE, total - pos);
ofs.write(big_data + pos, write_size);
pos += write_size;
}
ofs.close();
return 0;
}
进阶方法(seekp)原型及参数解释
- ofstream::seekp :
ostream& seekp(streampos pos);或ostream& seekp(streamoff off, ios_base::seekdir dir);
参数1(pos/off):指针位置(绝对位置pos,或相对偏移off);
参数2(dir):偏移基准(ios::beg=文件起始、ios::cur=当前位置、ios::end=文件末尾);
功能:调整输出流指针,实现指定位置写入。
FILE*与ofstream对比建议
| 写入方式(含进阶) | 优势 | 劣势 | 推荐场景 |
|---|---|---|---|
| FILE*写入 | 兼容强、性能高、底层可控,支持fseek定位 | C风格、需手动管理指针 | 嵌入式、混合编译、老项目 |
| ofstream写入 | C++原生、跨平台、安全简洁,支持seekp定位与分块 | 性能略低于fwrite | 日常项目、新手、纯C++环境,需灵活写入场景 |
选型总结:新手优先ofstream(最简版),兼容场景用FILE*(最简版);