Reading from a binary file I've just written to

Hello,

I've just begun learning about binary files, and I'm having trouble reading what I've just written (at least tried to write) to the file "this.bin". I was able to retrieve the data when I used separate streams for input and output but I would like to learn how to retrieve the data using a single fstream. The following code returns nothing.
Please help,
Thank you!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  #include <iostream>
  #include <fstream>
   using namespace std;

  int main()
{
    char num='1';
    
    fstream file("this.bin",ios::in|ios::out|ios::binary);
    
    file.write((char*)&num,sizeof(num));
    
    file.seekg(0);
    char retrieve;

    file.read((char*)&retrieve,sizeof(retrieve));
    
    cout<<retrieve;
    
    file.close();
    return 0;
}
If you attempt to open the file for input (ios::in), the file must already exist. Otherwise this will result in an error and all subsequent use of the file will fail.
Are you sure the file opened correctly? You should always check that the file opens correctly.

You're missing the flag std::ios::app (or std::ios::trunc). This is necessary if the file doesn't exist already (and you want it to be created).

file.write((char*)&num,sizeof(num));
This is fine, although it is strongly recommended to avoid c-style casts:
file.write(static_cast<char*>(&num), sizeof (num));
Of course, &num is a char* already.

Last edited on
Thank you, everyone! Regarding the c-style cast, I have another question. When I try to the run the following code...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    char array[5]=
    {
    
        '1','1','1','0','1'
    
    };
    char newarray[5];
    fstream file("brainfart.bin",ios::in|ios::out|ios::trunc);

    file.write((char*)&array,sizeof(array));
    
    file.seekg(0);
    file.read((char*)&newarray,sizeof(newarray));
    
    for(int i=0;i<5;i++)
    {
        cout<<newarray[i]<<" ";
    }
    cout<<endl;
    
    
    
    return 0;
}


...it works. But if I replace the c-style casts with static_cast, I get this error: "Static_cast from 'char(*)[5]' to 'char*' is not allowed". I'm using Xcode btw, in case that changes anything with regards to this error. Thanks again!
static_cast does not perform the unsafe conversion between pointers to unrelated types. That's the job of reinterpret_cast, which you would use when trying to write something that's not a char or array of it.

The C-style cast tries very hard to coerce one type to another, even doing things that are often blatantly wrong (e.g. by silently removing cv-qualifiers), while the C++-style casts would fail to compile. Basically the C-style cast repeatedly applies "enhanced" C++-style casts until a sequence is found. For this reason, the C++-style casts are superior.

Array types may undergo an implicit array-to-pointer conversion. This means that an expression of array type can be converted to a pointer to the first element of the array. This doesn't happen here: the expression &array_name is a pointer to an array.

Where array is exactly an array of char, unsigned char, signed char, or std::byte, the following is correct:
file.write(array, sizeof(array));

Although that's awfully fragile, as its correctness depends on the type of array. In particular, for arrays of T where sizeof(T) != sizeof(char), sizeof(array) is not the number of elements in the array. Further, it's common to mistake pointers for arrays: best practice suggests always passing a size explicitly.

To write and read, e.g., an array of int:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <fstream>

int main() {
  static constexpr int sz = 5;

  std::fstream file("brainfart.bin", std::ios::in | std::ios::out |
                    std::ios::trunc);

  // write out
  int write_from[sz] = { 10, 20, 30, 40, 50 };
  if (! file.write(reinterpret_cast<char const*>(write_from),
                   sz * sizeof *write_from))
  { std::cerr << "write failed\n"; return 1; }

  // Seek to the beginning
  file.seekg(0);

  // read in
  int read_into[sz];
  if (! file.read(reinterpret_cast<char*>(read_into),
                  sz * sizeof *read_into))
  { std::cerr << "read failed\n"; return 2; }

  for (auto const& elt: read_into) std::cout << elt << '\n';
}

http://coliru.stacked-crooked.com/a/4f672ea7fffc706d
Last edited on
Thank you for the explanation and all of your help!
Topic archived. No new replies allowed.