Problem when reading from a file with read() and write()

Hi everyone
I am a new programmer and can't get this code to work
The program should get a name and phone number from the user, write it to a file using write(), and then when the user runs the program for a second time, read from the file using read() and display the information on the screen
The problem is that when you run the program for a second time, the program runs but it does not display the strings read by read() on the screen, as if the string were never read to the program. The program writes to a file without a problem (but the contents of the file seem strage, but I have never tried to work with binary file I/O before so I wouldn't know)
I have tried time and again to solve the problem, but I have no idea.
If anyone can help, thanks in advance.

The program seems pointless, but I was just truing to test stuff out, I know that a single phone number storing program is really not very useful.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//To read and write any data type to a file
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> 

using namespace std;

/*Here is the function that reads and writes*/


template <class theType> void ffReadWrite(char action, const char *fileName, theType *objectPointer)
{
	switch(action)
	{
		case 'r':
		{
			ifstream in(fileName, ios::in | ios::binary);
			
			if(!in)
			{
				cout << "\a\nFOXEN: Cannot open file\n";
				system("pause");
				exit(1);
			}

			in.read((char *) &objectPointer, sizeof(theType));
			
			if(!in.good())
			{
				cout << "FOXEN: Error reading from file";
				system("pause");
				exit(1);
			}

			in.close();
			break;
		}
		case 'w':
		{
			ofstream out(fileName, ios::out | ios::trunc);
			
			if(!out)
			{
				cout << "\a\nFOXEN: Cannot open file\n";
				system("pause");
				exit(1);
			}
			
			out.write((char *) &objectPointer, sizeof(theType));
			if(!out.good())
			{
				cout << "FOXEN: Error writing to file";
				system("pause");
				exit(1);
			}

			out.close();
			break;
		}
		default:
		{
			cout << "\a\nFOXEN: Enter 'r' to read or 'w' to write in ARRG char action";
			system("pause");
			exit(1);
		}
	}
return;
}

void example();//the example function

int main()
{	
	example();
	return 0;
}

//Here is the example using the PhoneNum class
//It lets you read or write info about phone numbers using the PhoneNum class
//If you write, It asks for a name and phone number and then saves the class to a bin file
//If you read, It will show you the old info you input on the last run of the program

//Here is the class PhoneNum
class PhoneNum
{
public:
	string number;
	string name;
};

//Here is the example function
void example()
{
	PhoneNum myNumber;

	cout << "\aWelcome to the Phone number storage program\n"
		 << "The easy way to store one phone number!"
	     << "\n\nWhat do you want to do?"
		 << "\n\t1:Read a previously saved number"
		 << "\n\t2:Write a new number"
		 << "\n\t3:Exit"
		 << "\nChoice : ";
	char choice;
	cin >> choice;
	
	switch(choice)
	{
		case '1':
		{
			ffReadWrite('r', "PHONE_NUM", &myNumber);
			cout << "\n\n" << myNumber.name << " has the number " << myNumber.number;
			system("pause");
			exit(0);
		}
		case '2' :
		{
			cout << "\n\nEnter a name (Remember i'm using cin for this, so no spaces)\nNAME : ";
			cin >> myNumber.name;
			cout << "\nEnter a number\nNUMBER : ";
			cin >> myNumber.number;
			ffReadWrite('w', "PHONE_NUM", &myNumber);
			cout << "\n\nDone.";
			exit(0);
		}
		default :
			exit(1);
	}
return;
}

Thanks again.
Rule #1 of serialization: Do NOT directly convert an object to a stream of bits.

std::string contains, among other things, a pointer. This ensures than any attempt to fill it with raw binary data will never succeed except by some miracle. Furthermore, you shouldn't do this with any multy-byte data type unless you're completely sure that the CPU uses the same endianness as the source you're reading the data from.
The correct way of serializing is to break down a datum to its basic parts until you're only left with raw bytes, and write them in a consistent manner. Reading is the reverse process.

For example, to serialize an integer, first you choose an endianness for the stream. For my example, I'll use little endian. Then you decompose the integer into bytes. In order to do this, you need to know the size of the integer.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void writeULong(std::ostream &stream,ulong n){
    //Obtain the size of ulong at compile time.
    static const ulong size=sizeof(n);
    //Do once per byte in n.
    for (int a=0;a<size;a++){
        //Assign to byte the least significant byte in the integer. 0xFF is hex
        //notation for 255.
        char byte=n&0xFF;
        //Actually write the byte.
        stream.put(byte);
        //Shift n 1 byte to the right. If n was 0x12345678, it will now be
        //0x00123456.
        n>>=8;
    }
    //If n was originally 0x12345678, the stream now contains 78 56 34 12.
}

You get the solution for writing an integer for free, but you still need to figure out how to read and how to write and read a string. Keep in mind that std::strings have a size and that it's safe to assume that chars are never more than 1 byte long.
Topic archived. No new replies allowed.