前言
之前,我们使用传统C语言写了一个游戏的存档、读档程序。
但是,需要存储的数据过多时,就会出现这样的情况:
void saveGame(){
FILE * fp = fopen("...", "w");
fprintf(fp, "%d %d %d %d %d %d %d %d %d %d...",
a, b, c, d, e, f, g, h, i, j...);
}
这么写很容易就会漏掉或使数据错位,导致读写不一致。
因此,我们就可以使用强大的C++文件读写库!
fstream库认识
这一节只是介绍C++的文件读写库,与本文标题无关,已经了解的可以直接跳到后边。
首先来看一段代码:
#include<fstream>
#include<string>
void test(){
ofstream file;
file.open("test.txt", ios::out);
// fstream file("test.txt", ios::out);
string s = "this is a test";
file.write(s, sizeof(s));
// 或者写成 file << s << endl; 使用重载的<<操作符
file.close();
file.open("test.txt", ios::out|ios::in);
}
这里我们先导入fstream头文件。这个头文件主要包含文件的读写。
在第5行,我们定义了一个“类型”为ofstream(文件写入模式)的对象file。以后的所有操作都是在它的基础上完成的。
第6行,我们找到了一个名为test.txt的文件,以ios::out方式打开。当然,也可以像11行一样同时以多个方式打开,中间用“ | ”符号隔开。
(第7行是另一种简便写法,和第5、6行等价)
第8-9行,我们向文件中写入一个字符串s,传进s和它的大小即可。
最后,我们关闭文件。
读的话,用这个:
ifstream in("test.txt", ios::in);
string s;
in.read((char*)&s, sizeof(s));
顺带说一句,文件的读写本质上都是有个文件指针,定义时用in或out是指针指向文件头,
写入时用ios::app把指针移到末尾,也就可以往文件末尾添加数,而不是删掉重写了。
很简单,对不对?
二进制文件读写结构体[正文]
假设我们有如下结构体存放数据:
struct Player{
int gold, lvl, exp;
string name;
......
}player;
首先,传统C的写入方式容易弄错;而非二进制的C++文件读写则会导致空间的浪费。
因此,我们选择用二进制读写文件。
用ofstream::write()写入文件
ofstream 和 fstream 的 write() 函数用法差不多,其功能是将内存中 buffer 指向的 count 个字节的内容写入文件,基本格式如下:
ofstream & write(char* buffer, int count);
这里为了方便讲解,使用 ostream 声明文件(即文件输出对象)。
ofstream file("game.dat", ios::out | ios::binary)
其中,ios::out表明对文件内容进行写操作,ios::binary说明这是二进制运算。
这样,写入时就可以把整个结构体写进去了
void saveGame(){
ofstream file("game.dat", ios::out|ios::binary); //打开文件
file.write((char*)&player, sizeof(player)); //写入
file.close(); //关闭
}
同样,再写一个函数把它读出来:
void readGame(){
ifstream file("game.dat", ios::in|ios::binary); //打开
if(!file){ //判断文件是否不存在
cout << "error" << endl; //不存在就报错
return ;
}
file.read((char*)&player, sizeof(player)); //读入
file.close(); //关闭文件
}
其中,第三行的 ! file 表示判断文件是否不存在,如果不存在为真,报错。
完整程序如下:
#include<bits/stdc++.h>
#include<fstream>
using namespace std;
struct Player{
int gold, maxHP, HP;
string name;
}player;
void saveGame(){
ofstream file("game.dat", ios::out|ios::binary);
file.write((char*)&player, sizeof(player));
file.close();
}
void readGame(){
ifstream file("game.dat", ios::in|ios::binary);
if(!file){
cout << "error" << endl;
return ;
}
file.read((char*)&player, sizeof(player));
file.close();
}
int main()
{
player.gold = 0;
player.HP = 100;
player.maxHP = 100;
player.name = "a name";
saveGame();
cout << player.gold << ' ' << player.HP << ' ' << player.maxHP << endl;
cout << player.name << endl;
return 0;
}
执行代码,运行结果为:
0 100 100
a name
而文件中的内容在作者的环境下是这样的:
d d ??
所以,不用担心普通玩家恶意篡改文件内容导致破坏游戏平衡。
那这篇文章就到这里了,最后感谢大家的阅读,我们下次再见!
【题外话】最近一年多没更新了,可能这篇文章写得也不咋的,以后尽量保持月更,
希望大家谅解、支持。你们的赞是对我最大的鼓励,谢谢!