Reading from a binary file I've just written to

Jul 13, 2017 at 8:59pm
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;
}
Jul 13, 2017 at 9:09pm
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.
Jul 13, 2017 at 9:11pm
Are you sure the file opened correctly? You should always check that the file opens correctly.

Jul 13, 2017 at 9:22pm
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 Jul 13, 2017 at 9:36pm
Jul 13, 2017 at 10:20pm
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!
Jul 13, 2017 at 11:44pm
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 Jul 13, 2017 at 11:53pm
Jul 14, 2017 at 3:36am
Thank you for the explanation and all of your help!
Topic archived. No new replies allowed.