Im learning SDL2 and now im trying to save a game ranking into a .bin file. I have placed the ranking data into a vector. But im unable to save the data. Perhabs it has to do with file size, but im unable to solve that. This is the code that im using now:
class Player {
private:
std::string name, faction, dific;
int points;
public:
Player() {};
virtual ~Player() {};
void addName(std::string s);
void addFacti(std::string s);
void addDific(std::string s);
void addPoint(int p);
std::string getName() const;
std::string getFacti() const;
std::string getDific() const;
int getPoint() const;
bool operator>(const Player& p) const;
};
Player p1; Player p2;//just two examples
//add properties to each object
std::vector<Player>classi;
classi.push_back(p1); classi.push_back(p2);
std::sort(classi.begin(), classi.end(), std::greater<Player>());
//load file
SDL_RWops* rankfile = SDL_RWFromFile("ranking.bin", "r+b");
for (int i = 0; i < classi.size(); ++i) { SDL_RWread(rankfile, &classi[i], sizeof(Player), 1); }
SDL_RWclose(rankfile);
//im able to render the objects
//save file - but it doesnt save anything
rankfile = SDL_RWFromFile("ranking.bin", "w+b");
for (int i = 0; i < classi.size(); ++i) { SDL_RWwrite(rankfile, &classi[i], sizeof(Player), 1); }
SDL_RWclose(rankfile);
Here's an example of how I might serialize a struct containing std::string
to/from binary. It doesn't use the SDL functions because I don't use SDL but it wouldn't be difficult to modify if desired.
You may have a different problem since you say your file is empty, and I am concerned that you try and read the file before you write it, but you could try something like this and see if it helps.
#include <iostream>
#include <string>
#include <fstream>
#include <tuple>
template <typename T>
std::ostream &writeBinary(std::ostream &f, T data)
{
return f.write(reinterpret_cast<char *>(&data), sizeof(data));
}
std::ostream &writeBinary(std::ostream &f, const std::string &str)
{
// If file size is a concern you might use a smaller type like uint16_t.
// Just make sure to mirror the change in readBinary.
std::string::size_type sz = str.size();
if (f)
{
f.write(reinterpret_cast<char *>(&sz), sizeof(sz));
}
if (f)
{
f.write(str.data(), str.size());
}
return f;
}
template <typename T>
std::istream &readBinary(std::istream &f, T &data)
{
if (f)
{
f.read(reinterpret_cast<char *>(&data), sizeof(data));
}
return f;
}
std::istream &readBinary(std::istream &f, std::string &str)
{
std::string::size_type sz = 0;
if (f)
{
f.read(reinterpret_cast<char *>(&sz), sizeof(sz));
}
if (f)
{
str.resize(sz);
f.read(str.data(), sz);
}
return f;
}
struct Thing
{
std::string shortString;
int i;
double d;
std::string longString;
Thing()
: i(99)
, d(99.99)
{ }
bool operator==(const Thing &rhs) const
{
return std::tie(shortString, i, d, longString)
== std::tie(rhs.shortString, rhs.i, rhs.d, rhs.longString);
}
bool write(std::ofstream &f)
{
if (!writeBinary(f, shortString))
{
return false;
}
if (!writeBinary(f, i))
{
return false;
}
if (!writeBinary(f, d))
{
return false;
}
if (!writeBinary(f, longString))
{
return false;
}
return true;
}
bool read(std::ifstream &f)
{
if (!readBinary(f, shortString))
{
return false;
}
if (!readBinary(f, i))
{
return false;
}
if (!readBinary(f, d))
{
return false;
}
if (!readBinary(f, longString))
{
return false;
}
return true;
}
};
std::ostream &operator<<(std::ostream &o, const Thing &t)
{
return o << "'" << t.shortString << "'" << ", "
<< t.i << ", " << t.d << ", "
<< "'" << t.longString << "'";
}
int main()
{
Thing t1;
// Shorter string to hopefully fit in any short string optimization buffer in the string.
t1.shortString = "Short";
t1.longString = "Long string that should be long enough to not fit in the SSO buffer.";
t1.i = 42;
t1.d = 42.42;
std::cout << "t1 Before Write: " << t1 << "\n";
std::ofstream out("thing.bin", std::ios::binary);
if (!t1.write(out))
{
std::cout << "Error writing t1!\n";
return -1;
}
out.close();
std::cout << "t1 After Write: " << t1 << "\n";
Thing t2;
std::cout << "t2 Before Read: " << t2 << "\n";
std::ifstream in("thing.bin", std::ios::binary);
if (!t2.read(in))
{
std::cout << "Error reading t2!\n";
return -1;
}
in.close();
std::cout << "t2 After Read: " << t2 << "\n";
std::cout << "t1 == t2: " << std::boolalpha << (t1 == t2) << "\n";
return 0;
}