Ok, lets go through it step by step:
But it is creating an empty file
That is because you are emptying the file with
std::fstream::trunc - Delete everything in the file (truncate it)
Meaning the moment you open your data.data file you erase all data in it if any is already present.
There are two standard formats in 'std::fstream':
format is the std::ios::binary format, data.data is not readable with a text editor but it is compact and efficient. Y
format is storing the strings in printable characters.
in that case data.data is readable like a txt-file with a common file editor.
Since @Andreas H. provided a binary file format example and you didn't used the binary format, I provide a minimal executable example that stores your data with printable characters.
int main(int argc, char *argv[]) needs [ ]-brackets to work properly
Type casting in the old c-style (char*)&this->db; is working fine, Scott Meyers writes in "Effective C++" old c-style should be avoided because because old-c type casting is not type safe and "hides" in the code so it is not easy to find like static_cast<char*>(...)
Here you see the difference - both are doing the same thing:
int firstNumber = 1, secondNumber = 2;
double result1 = ((double)firstNumber) /secondNumber;
double result2 = static_cast<double>(firstNumber)/secondNumber;
std::cout << result1 << std::endl;
std::cout << result2 << std::endl;
For the sake of providing a minimal executable example and
a better understanding I skipped the class ;)
Should be easy enough for you to parse it in a nice interface.
#include <iostream>
#include <map>
#include <fstream>
#include <string>
int main(int argc, char *argv[])
{
std::map<std::string, std::string> db{{"Key1","value"},{"Key2","value"}};
std::fstream mydata;
//PRINT MAP
for(const auto &[k,v] : db)
std::cout << k << " " << v << std::endl;
//WRITE MAP TO FILE
//Open File in write mode
mydata.open("data.data", std::ios::out);
if(!mydata.is_open())
std::cout << "Could not open file!" << std::endl;
//Write data to file
for(const auto &[k,v] : db)
mydata << k <<" " << v << std::endl;
//Close file
mydata.close();
//proof of concept, DESTROY MAP VALUES
db.clear();
//READ MAP BACK IN FROM FILE
std::string key , value;
//Open Data in read mode
mydata.open("data.data", std::ios::in);
if(!mydata.is_open())
std::cout << "Could not open file!" << std::endl;
//Read data back to map
while(mydata >> key >> value)
db[key] = value;
//Close File again
mydata.close();
//PRINT MAP
for(const auto &[k,v] : db){
std::cout << k << " " << v << std::endl;
}
return 0;
}
I hope this will help you finish your project :)
Btw. if you have more than one word as key or value, you can use getline with a delimiter, and store your data file in a csv-format (coma separated values file) for easy import of your data f.e. in email software if you store contact data in your database.
Just as an exercise for me I wrote a minimal executable example to write a map of strings in a binary format to a file:
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#define FILENAME "BinaryMap.bin"
int main()
{
std::fstream file;
std::string key{"Key One"}, value{"Value One"};
std::map<std::string, std::string> map{{key,value},{"Key Two","Value Two"}};
//Print Map
for(const auto &[key,value] : map){
std::cout << key << " " << value << '\n';
}
//Open file and check for errors
file.open(FILENAME, std::ios::binary | std::ios::out);
if(!file.is_open())
std::cout << "Could not open file!" << '\n';
//Position write cursor to the beginning of the file
file.seekp(0);
//Write the number of entries
size_t entries = map.size();
file.write(reinterpret_cast<const char*>(&entries), sizeof(entries));
//Write the number of entries
for(auto& it : map){
//Write the lenth of the key string to the file
size_t len = it.first.size();
file.write(reinterpret_cast<char*>(&len), sizeof(len));
//Write the string itself to the file
file.write(it.first.data(), it.first.size());
//Write the length of the value string to the file
len = it.second.size();
file.write(reinterpret_cast<char*>(&len), sizeof(len));
//Write the value string itself to the file
file.write(it.second.data(), it.second.size());
}
//Close the file
file.close();
map.clear();
std::cout << "--------clear---------" << '\n';
//READ STUFF
file.open(FILENAME, std::ios::binary | std::ios::in);
if(!file.is_open())
std::cout << "Could not open file!" << '\n';
// Position read cursor to the beginning
file.seekg(0);
// read the number of entries
entries = 0;
file.read(reinterpret_cast<char*>(&entries), sizeof(entries));
//Read the length of the string stored in the file
size_t length {};
for(size_t i = 0; i < entries; ++i){
//Read the length of the string in the file
if(file.read(reinterpret_cast<char*>(&length), sizeof(length)).fail())
std::cout << "Failed to read bin" << '\n';
//Pointer to variable address
std::string* p_target = &key;
//Preallocate memory for the string
p_target->resize(length);
//Read string from file
file.read(&p_target->front(), p_target->size()).good();
//Read the length of the string in the file
if(file.read(reinterpret_cast<char*>(&length), sizeof(length)).fail())
std::cout << "Failed to read bin" << '\n';
//Dereference value
key = *p_target;
//Assign variable address to pointer
p_target = &value;
//Preallocate memory for the string
p_target->resize(length);
//Read string from file
file.read(&p_target->front(), p_target->size()).good();
//Dereference value
value = *p_target;
//Write key and value to map
map[key] = value;
}
//Close the file
file.close();
for(const auto &[key,value] : map){
std::cout << key << " " << value << '\n';
}
std::cout << "Hit 'return' to continue";
std::cin.get();
return 0;
}