1

ok so im on the 2nd Semester on my unversity have done c and doing c++ now doing the project in DevC.

Currently im making a program that will do the charging processes of a shop while having and editing the database.

Tried writing and reading a full struct but dosent work so i went down writing 2 int numbers and reading them but this also dosent work while getting random number when reading even though if i write txt the numbers seem ok.

//write and read are different fucntion only 1 is called .
//file creation code
int AccountNumber=0;
ofstream FileCreator("Database.dat",ios::binary);   
FileCreator<<AccountNumber;
AccountNumber=1;
FileCreator<<AccountNumber;

and

//reading code

int AccountNumber=0;
ifstream FileCreator("Database.dat",ios::binary);
FileCreator.seekg(0,ios::beg);

FileCreator.read(reinterpret_cast<char*>(&AccountNumber), sizeof(AccountNumber));
cout<<AccountNumber<<endl;
FileCreator.read(reinterpret_cast<char*>(&AccountNumber), sizeof(AccountNumber));
cout<<AccountNumber<<endl;

I expect 0 and 1 at the output but get 12592 and 12592.

7
  • 6
    For binary writing, use std::ostream::write, not operator<<. So, FileCreator<<AccountNumber should be replaced by FileCreator.write((char *) &AccountNumber, sizeof(AccountNumber)). Commented Apr 29, 2019 at 15:54
  • you mean you expect 0 and 1 (not 50) Commented Apr 29, 2019 at 15:55
  • 1
    Hello EJLH. Unrelated, but might be of interest to you: minimal reproducible example. Commented Apr 29, 2019 at 15:56
  • @ThomasMatthews ooof that fixed it thank you :D .but why does it matter ? does << write differently that .write in binary files ? Commented Apr 29, 2019 at 16:00
  • to open in binary is only useful under Windows to not have the \n transformed on the fly to \c\n Commented Apr 29, 2019 at 16:02

2 Answers 2

1

To complete the answer of @Thomas Matthews

but why does it matter ? does << write differently that .write in binary files ?

Out of windows you will not see a difference, under windows the \n are saved/read unchanged if the file open in binary mode, else a writting \n produces \r\n and reading \c\n returns \n. It like the difference between "r"/"rb" and "w"/"wb" for fopen.

You can mix the use of the operator <</>> and read/write in binary mode or not but you have to take care of the separators, for instance :

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
  int AccountNumber = 123;

  {
    ofstream bin("bin",ios::binary);   

    bin << AccountNumber << '\n'; // a \n to finish the number allowing to read it later
    bin.write((char *) &AccountNumber, sizeof(AccountNumber));
  }
  {
    ofstream txt("txt");   

    txt << AccountNumber << '\n';
    txt.write((char *) &AccountNumber, sizeof(AccountNumber));
  }
  {
    ifstream bin("bin",ios::binary);

    AccountNumber = 0;
    bin >> AccountNumber;
    cout << AccountNumber << endl;

    // I have to read the \n with read() because >> bypass it.
    // Supposing I written '@' rather than '\n' `bin >> c;` can be used
    char c;

    bin.read(&c, 1);
    cout << (int) c << endl;

    AccountNumber = 0;
    bin.read((char *) &AccountNumber, sizeof(AccountNumber));
    cout << AccountNumber << endl;
  }

  return 0;
}

Compilation and execution (out of Windows) :

pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -Wall f.cc
pi@raspberrypi:/tmp $ ./a.out
123
10
123
pi@raspberrypi:/tmp $ cmp txt bin
pi@raspberrypi:/tmp $ 

I am not under Windows so to use the binary mode or not changes nothing, the two files are identical

Sign up to request clarification or add additional context in comments.

3 Comments

I'm not sure but I suspect that bin.read(&c, 1); won't work well on Windows. bin.ignore(); would probably be better.
Turns out, neither bin.read(&c, 1); nor bin.ignore(); works in binary mode on windows. One has to manually read the 2 EOL chars. So mixing stream operators and read/write seems to be a little more complicated on Windows.
@TedLyngmo yes, the auto transformation between \n and \c\n is only active when using the operator <</>>, so a mix operator/function for \n is a problem under Windows
0

For writing binary files, use std::ostream::write() method, not operator<<:

FileCreator.write((char *) &AccountNumber, sizeof(AccountNumber));

The cast is necessary because there is no overload for writing integers to the stream.

Remember, read and write are paired for binary I/O.

Edit 1: Fixed length & variable length records
Be aware that you need the size of the item when writing and reading. This will work for fixed size/length data items and structures. However, it does not work well with variable length data, such as text.

For variable length records, you may want to write the length first followed by the data:

static const char hello[] = "Hello";
static const unsigned int data_size(sizeof(hello) - 1);
FileCreator.write((char *) &data_size, sizeof(data_size));
FileCreator.write(&hello[0], data_size);

In the above example, the "- 1" is there so that the terminating NUL character is not written to the file. You don't need this for binary files, but YMMV (I use the idiom when writing to console and other human readable streams).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.