FWIW, here is an example of writing and reading binary data, it is more C than C++, but good enough for demonstrating reading and writing. You can see that doing it correctly by yourself quite cumbersome. That is why I think it is best to employ a library doing that for you (such as SQLite for records), even if you think it is an overkill for the task.
Code: Select all
bool WritePersonToStream(wxOutputStream& stream, const Person& person)
const wxScopedCharBuffer nameUTF8(person.name.ToUTF8());
const wxUint64 nameUTF8size = nameUTF8.length();
const uint8_t marriedInt = person.married;
return stream.WriteAll(&nameUTF8size, sizeof(nameUTF8size))
&& stream.WriteAll(nameUTF8.data(), nameUTF8.length())
&& stream.WriteAll(&person.age, sizeof(person.age))
&& stream.WriteAll(&marriedInt, sizeof(marriedInt));
bool ReadPersonFromStream(wxInputStream& stream, Person& person)
wxUint64 nameUTF8size = 0;
uint8_t age = 0;
uint8_t marriedInt = 0;
if ( !stream.ReadAll(&nameUTF8size, sizeof(nameUTF8size)) )
if ( !stream.ReadAll(nameUTF8.data(), nameUTF8.length()) )
if ( !stream.ReadAll(&age, sizeof(age)) )
if ( !stream.ReadAll(&marriedInt, sizeof(marriedInt)) )
person.name = wxString::FromUTF8(nameUTF8);
person.age = age;
person.married = marriedInt == 1 ? true : false;
class MyApp : public wxApp
bool OnInit() override
wxFFileStream stream("Persons.per", "w+b");
person.name = "John Smith";
person.age = 30;
person.married = true;
if ( !WritePersonToStream(stream, person) )
wxLogError("Could not write person to stream.");
person.name = ""; person.age = 0; person.married = false;
if ( !ReadPersonFromStream(stream, person) )
wxLogError("Could not read person from stream.");
s << "Name: " << person.name << " Age: " << person.age
<< "Married: " << person.married;
Please notice that when writing a binary file, some standards should be always employed. I.e, the character encoding and types sizes must not be build dependent, e.g., wchar_t is 16-bit on Windows but 32-bit on Linux, size_t is 4 bytes in 32-bit build but 8 bytes in 64-bit build etc. Similarly, do not use types whose size is implementation-defined, such as bool.
Additionally, when storing "records" one should consider whether to not make string fields fixed-width. Doing that allows quick seeking between the records without the need to parse all the records between.
Last but not least, make sure you know what all the file modes mean so you are not surprised that opening the file e.g."w+" creates an empty file.
BTW, either way, as I already shown you, I would not recommend reading or writing strings byte-by-byte, that is very slow, buffered IO or not.
You also have a bug in your read string code
Code: Select all
ws = "";
for (int i = 0; i < ws.size(); i++)
Executing wx= ""
will make ws.size()
return 0 and the code inside the loop will be never executed, you wanted to use size