|
-
August 4th, 2006, 01:02 PM
#1
How to write/read class to a binary file properly???
Code:
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <fstream>
#include <vector>
#include "shortphone.cpp"
#include "shortname.cpp"
#include "shortaddress.cpp"
using namespace std;
class Record{
shortName Name;
shortAddress Address;
shortPhone Phone;
public:
void AddNewRecord();
void ViewRecord();
void InFile();
void OutFile();
int FindRecord();
};
int menu()
{
int choice;
cout <<" Record List Processing System "<<endl;
cout <<"1. Add New Record "<<endl;
cout <<"2. Remove A Record Object from the list"<<endl;
cout <<"3. View all record object"<<endl;
cout <<"4. Find the object"<<endl;
cout <<"5. Exit"<<endl;
cin >> choice;
return choice;
}
void Read_Str(string str)
{
ofstream fout("info.dat", ios::binary|ios::app);
string data;
data = str;
int tmp = data.size();
fout.write(reinterpret_cast<char *>(&tmp),sizeof(int));
fout.write(reinterpret_cast<char *>(&data), sizeof(tmp) );
fout.write(data.c_str(), tmp+1);
fout.close();
}
void Record::InFile()
{
Read_Str(Name.getFirst());
Read_Str(Name.getLast());
Read_Str(Address.getCity());
Read_Str(Address.getID());
Read_Str(Address.getState());
Read_Str(Address.getStreet());
Read_Str(Address.getZip());
Read_Str(Phone.getArea());
Read_Str(Phone.getNumber());
Read_Str(Phone.getPrefix());
}
void Record::AddNewRecord()
{
cin.ignore();
string input;
cout << "First Name :";
getline(cin,input,'\n');
Name.setFirst(input);
cout << "Last Name :";
getline(cin,input,'\n');
Name.setLast(input);
cout << "ID: :"; //Address
getline(cin,input,'\n');
Address.setID(input);
cout << "Street :";
getline(cin,input,'\n');
Address.setStreet(input);
cout << "City :";
getline(cin,input,'\n');
Address.setCity(input);
cout << "State :";
getline(cin,input,'\n');
Address.setState(input);
cout << "Zip :";
getline(cin,input,'\n');
Address.setZip(input);
cout << "Area Code :";
getline(cin,input,'\n');
Phone.setArea(input);
cout << "Telephone - Prefix :";
getline(cin,input,'\n');
Phone.setPrefix(input);
cout << "Telephone - Numbers:";
getline(cin,input,'\n');
Phone.setNumber(input);
input.erase();
}
void Record::ViewRecord()
{
cout << Name.getFirst() <<" " << Name.getLast() <<" ";
cout << Address.getID() <<" " << Address.getCity() <<" " << Address.getStreet() <<" " << Address.getState() <<" " << Address.getZip() <<setw(4) ;
cout << Phone.getArea() <<" " <<Phone.getPrefix() <<"-" << Phone.getNumber() <<endl;
}
int Record::FindRecord()
{
cin.ignore();
string input,last_name;
int i = 1;
last_name = Name.getLast();
cout <<"Enter the last name :";
getline(cin, input);
i=last_name.compare(input);
return i;
}
typedef vector<Record> SetRecord;
int main()
{
SetRecord GrowingRecord;
for(;;){
int choice = menu();
switch(choice)
{
case(1):
{
Record Employee;
Employee.AddNewRecord();
Employee.InFile();
GrowingRecord.push_back (Employee);
break;
}
case(2):
{
int i,j;
cout <<"Index " << " Name " << setw(2) << " ID " << setw(2) << " Street " << setw(5) << " City " << setw(5) <<"State "<<setw(2) << " Telephone " <<endl;
for(i=0; i<GrowingRecord.size();i++)
{
Record Employee;
Employee = GrowingRecord[i];
cout << i << setw(2);
Employee.ViewRecord();
}
if(i==0){
cout <<"No Records Exist! "<<endl;
break;
}
cout << "Which record do you wish to delete (-1 to exit) ? (0-" << i-1 <<")" ;
cin >> j;
GrowingRecord.erase(GrowingRecord.begin()+j);
}
break;
case(3):
{
cout <<"Index " << " Name " << setw(2) << " ID " << setw(2) << " Street " << setw(5) << " City " << setw(5) <<"State "<<setw(2) << " Telephone " <<endl;
for(int i=0; i<GrowingRecord.size();i++)
{
Record Employee;
Employee = GrowingRecord[i];
cout << i << " ";
Employee.ViewRecord();
}
Record Employee;
break;
}
case(4):
{
int j;
for(int i=0; i<GrowingRecord.size();i++)
{
Record Employee;
Employee = GrowingRecord[i];
if((j=Employee.FindRecord()==0)){
cout <<"Found !"<< "The data is located at " << i << "th data" <<endl; break;}
else
cout <<"Not Found !";
}
break;
}
case(5):
exit(1); break;
default:
cout <<"Error" << endl;
};
}
return 0;
}
here is the code...i got no problems when reading out the classes into a binary file....but it prints junk or nth when i read it back
can anyone figure out the problem??? many thanks
-
August 4th, 2006, 01:36 PM
#2
Re: How to write/read class to a binary file properly???
Code:
void Read_Str(string str)
{
ofstream fout("info.dat", ios::binary|ios::app);
string data;
data = str;
int tmp = data.size();
fout.write(reinterpret_cast<char *>(&tmp),sizeof(int));
fout.write(reinterpret_cast<char *>(&data), sizeof(tmp) );
fout.write(data.c_str(), tmp+1);
fout.close();
}
That code, especially
Code:
fout.write(reinterpret_cast<char *>(&data), sizeof(tmp) );
Is extremely wierd. First of all, you will not get good results writing an object that is not a POD (Plain Old Data) type in binary, as you do with that std::string. Secondly, you write only sizeof(tmp) bytes of the std::string to the file, only 4 bytes on a 32 bit machine.
Also funky about your code, is that you include other source files. This should not be necessary. You can have declarations of your classes and methods in header files, and include those in the source files that you need to, and then have other source files implement those methods. Generally good article: http://www.gamedev.net/reference/pro...ures/orgfiles/
-
August 4th, 2006, 01:49 PM
#3
Re: How to write/read class to a binary file properly???
 Originally Posted by Calculator
Code:
void Read_Str(string str)
{
ofstream fout("info.dat", ios::binary|ios::app);
string data;
data = str;
int tmp = data.size();
fout.write(reinterpret_cast<char *>(&tmp),sizeof(int));
fout.write(reinterpret_cast<char *>(&data), sizeof(tmp) );
fout.write(data.c_str(), tmp+1);
fout.close();
}
That code, especially
Code:
fout.write(reinterpret_cast<char *>(&data), sizeof(tmp) );
Is extremely wierd. First of all, you will not get good results writing an object that is not a POD (Plain Old Data) type in binary, as you do with that std::string. Secondly, you write only sizeof(tmp) bytes of the std::string to the file, only 4 bytes on a 32 bit machine.
Also funky about your code, is that you include other source files. This should not be necessary. You can have declarations of your classes and methods in header files, and include those in the source files that you need to, and then have other source files implement those methods. Generally good article: http://www.gamedev.net/reference/pro...ures/orgfiles/
thx for your reply...
actually these 3 extra headers are already written by my teacher....
can you tell me how to write the code correctly?
-
August 4th, 2006, 02:04 PM
#4
Re: How to write/read class to a binary file properly???
Well, as you have it, InFile outputs data because it uses Read_Str, which seems to write data. Little wierd, but okay? If your teacher told you to include those source files, you may show that article to him (if he/she is cool or something). I can only guess that OutFile, which reads in things ( ) is in one of those other source files, and I can't see how it is being read. But what you could do, is have length-prepended strings in your data file, or null-terminated strings (which do not know their own length) in the file. With length prepended, it would be like:
Code:
void Read_Str(string str)
{
ofstream fout("info.dat", ios::binary|ios::app);
int tmp = str.length();
fout.write(reinterpret_cast<char *>(&tmp),sizeof(tmp));
fout.write(data.c_str(), tmp);
// You wrote a length prepended string to the file.
// i.e. "Hello!" in the file would look like
// <binary data representing 6>Hello!
fout.close();
}
With null-terminated, it would be like:
Code:
void Read_Str(string str)
{
ofstream fout("info.dat", ios::binary|ios::app);
fout.write(data.c_str(), tmp + 1);
// You wrote a null-terminated c string
// i.e. "Hello!" in the file would look like
// Hello!\0
fout.close();
}
To read the strings from the file, you would for length prepended:
Code:
int length = 0;
inFile.read(reinterpret_cast<char*>(&length), sizeof length);
inFile.read(buffer, length);
string someString(buffer);
// Now some string is an std::string recreated from
// A length prepended string
Or for null terminated
Code:
string someString;
char tmp;
while((tmp = inFile.get()) != 0)
{
someString += tmp;
}
// Now someString was re-created from a
// null-terminated c string in the file
Or something.
-
August 5th, 2006, 01:27 AM
#5
Re: How to write/read class to a binary file properly???
nice.....eventually i got the first list of data entered
however, it encountered other problems when i push it into a vector.
i copied the code to the main(), and i ran the following code
Record Employee;
for(int i=1;i<10;i++)
{
while(outFile.good())
{
int length =0;
outFile.read(reinterpret_cast<char*>(&length), sizeof length);
outFile.read(buffer, length);
string SomeBuffer(buffer);
cout << buffer << endl;
Employee.OutFile(SomeBuffer,i);
}
}
it displays junk after a complete string.....why??
-
August 7th, 2006, 04:41 AM
#6
Re: How to write/read class to a binary file properly???
 Originally Posted by lost_scott
outFile.read(buffer, length);
string SomeBuffer(buffer);
cout << buffer << endl;
it displays junk after a complete string.....why??
You are constructing your string from a buffer that isn't null-terminated, yet you don't provide the length. You want:
Code:
string SomeBuffer(buffer, length);
-
August 7th, 2006, 09:12 AM
#7
Re: How to write/read class to a binary file properly???
There is no method to obtain a writable buffer to a string to write into, so to read back from the file you have to use vector<char> which does give you a writable buffer (of a variable size) and then copy the buffer.
Unfortunately this is also one of the inefficiencies of the standard library. firstly you create a vector of char which it has to initialise even though you don't need it initialised. Then after reading the contents in from a file (via yet another buffer that is used for the streambuf) you have to copy it into your string - string doesn't have a swap method with vector<char> - it can't because string isn't guaranteed to have a contiguous buffer.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|