0

I'm learning file handling in c++ from internet alone. I came across the read and write function. But the parameters they take confused me. So, I found the syntax as

fstream fout;
fout.write( (char *) &obj, sizeof(obj) );

and

fstream fin;
fin.read( (char *) &obj, sizeof(obj) );

In both of these, what is the function of char*? And how does it read and write the file?

  • 5
    Please read a good C++ book, trying to learn the language from random internet sources is unlikely to end well – UnholySheep Sep 28 '20 at 15:46
  • [The API](http://www.cplusplus.com/reference/fstream/fstream/) requires the buffer to be `char*` (or `const char*` for `write`). How to read and write the file will depend on the platform and the implementation of the standard library. – MikeCAT Sep 28 '20 at 15:46
  • 1
    The `(char*)` is there as a warning that the code is dangerous. Whether the code you've posted is correct or not depends entirely on what `obj` is, but unfortunately you don't say. This style of I/O is called binary I/O and as a beginner you probably shouldn't be using it. Stick to text I/O. And really, find a good book that can explain C++, you will save yourself a lot of grief. – john Sep 28 '20 at 15:47
  • This solution only works for a few kinds of `obj`. The type has to be trivially copyable which most types are not. – François Andrieux Sep 28 '20 at 15:47
  • syntax is secondary, your compiler can check that. You need a place where you can read about what they do. Rarely I need more than this: https://en.cppreference.com/w/cpp/io/basic_fstream – 463035818_is_not_an_ai Sep 28 '20 at 15:50
  • Ya i will try to get my hands on a good C++ book. I tried coding with these syntax, it worked but i didn't understand the process.@john – Rajaram Karki Sep 28 '20 at 15:50
  • Note that both examples are Undefined Behaviors! So basically find better book on C++, since current source you are using may be not trustworthy. Deepening on how `obj` looks like problem is small or very big. – Marek R Sep 28 '20 at 15:51
  • @MarekR> neither of the examples, taken out of context like this, invokes undefined behavior. First example is always fine (which does not mean you get a useful file, but the program cannot invoke undefined behavior). The second, that really depends on what's living there at that time. – spectras Sep 28 '20 at 16:03
  • @spectras https://youtu.be/_qzMpk-22cc – Marek R Sep 28 '20 at 16:05
  • @MarekR> I know the rules. The first example is casting to char*, which is always allowed. The second example depends on whether there is an object alive in that storage that's trivially copyable. – spectras Sep 28 '20 at 16:08

2 Answers2

1

The function fstream::read has the following function signature:

istream& read (char* s, streamsize n);

You need to cast your arguments to the correct type. (char*) tells the compiler to pretend &obj is the correct type. Usually, this is a really bad idea.

Instead, you should do it this way:

// C++ program to demonstrate getline() function 
  
#include <iostream> 
#include <string> 
using namespace std; 
  
int main() 
{ 
    string str; 
  
    fstream fin;
    getline(fin, str); // use cin instead to read from stdin
  
    return 0; 
} 

Source: https://www.geeksforgeeks.org/getline-string-c/

Luke
  • 565
  • 5
  • 19
  • 3
    Nope, you shouldn't use `using namespace std;` – deW1 Sep 28 '20 at 15:52
  • Note that if he was using read(), I assume he wanted to do binary I/O. So `getline` isn't the answer. The answer would be to do proper serialization/deserialization. – spectras Sep 28 '20 at 16:05
  • The `getline` function *eats* newline characters and they don't appear in the receiving variable. The `read` function reads characters without interpreting them, into the destination variable. – Thomas Matthews Sep 28 '20 at 17:50
0

The usage of the char * cast with read and write is to treat the obj variable as generic, continuous, characters (ignoring any structure).

The read function will read from the stream directly into the obj variable, without any byte translation or mapping to data members (fields). Note, pointers in classes or structures will be replaced with whatever value comes from the stream (which means the pointer will probably point to an invalid or improper location). Beware of padding issues.

The write function will the entire area of memory, occupied by obj, to the stream. Any padding between structure or class members will also be written. Values of pointers will be written to the stream, not the item that the pointer points to.

Note: these functions work "as-is". There are no conversions or translations of the data. For example, no conversion between Big Endain and Little Endian; no processing of the "end of line" or "end of file" characters. Basically mirror image data transfers.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154