Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Storing string into file

Status
Not open for further replies.

hughLg

Programmer
Feb 18, 2002
136
0
0
MY
I wanna write a program that storing the following struct of data into the binary file:

Code:
struct staff {
   string id; // maximum 8 characters.
   string name; // maximum 35 characters.
   string ic; // identity card number, maximum 14 character.
   unsigned short age;
   string remark; // no limit.
} employee;

I was noticed that the byte returned by sizeof(string) being 28, even though the string variable contains more then 28 characters. I tried the following:

Code:
write((const char *)&employee, sizeof(employee));

But next time when i retrieve by using function read(char *, size_t), the string fields are not what i expected.

So I break out the above structure by separating it from string fields, like this:

Code:
struct staff1 {
   unsigned id;
   unsigned name;
   unsigned ic;
   unsigned remark;
   
   unsigned short age;
} employee;

struct {
   string id; // maximum 8 characters.
   string name; // maximum 35 characters.
   string ic; // identity card number, maximum 14 character.
   string remark; // no limit.
} s;

I use the following way to collecting data and write to tge file:

Code:
#include <fstream>
#include <string>
#include <iostream>
using namespace std;

struct staff1 {
   unsigned id;
   unsigned name;
   unsigned ic;
   unsigned remark;
   
   unsigned short age;
} employee;

struct {
   string id; // maximum 8 characters.
   string name; // maximum 35 characters.
   string ic; // identity card number, maximum 14 character.
   string remark; // no limit.
} s;

int main() {
	if (0) {
		ofstream oStrF("str.dat", ios::out | ios::binary);
		ofstream oEmployeeF("employee.dat", ios::out | ios::binary);
		s.id = "01010101";
		employee.id = (s.id.length() + 1); // extra byte for null terminator.
		s.name = "ABC";
		employee.name = (s.name.length() + 1); // extra byte for null terminator.
		
		s.ic = "801010-12-5165";
		employee.ic = (s.ic.length() + 1); // extra byte for null terminator.
		s.remark = "OK";
		employee.remark = (s.remark.length() + 1); // extra byte for null terminator.
		employee.age = 21;

		oStrF.write((const char *)s.id.c_str(), employee.id);
		oStrF.write((const char *)s.name.c_str(), employee.name);
		oStrF.write((const char *)s.ic.c_str(), employee.ic);
		oStrF.write((const char *)s.remark.c_str(), employee.remark);
		oEmployeeF.write((const char *)&employee, sizeof(employee));
	}
	else {
		ifstream iStrF("str.dat", ios::in | ios::binary);
		ifstream iEmployeeF("employee.dat", ios::in | ios::binary);
		iEmployeeF.read((char *)&employee, sizeof(employee));
		// id.
		char *buf = new char[employee.id];
		iStrF.read((char *)buf, employee.id);
		cout << "ID: " << buf << endl;
		delete buf;
		// name.
		buf = new char[employee.name];
		iStrF.read((char *)buf, employee.name);
		cout << "NAME: " << buf << endl;
		delete buf;
		// ic.
		buf = new char[employee.ic];
		iStrF.read((char *)buf, employee.ic);
		cout << "IC: " << buf << endl;
		delete buf;
		// remark.
		buf = new char[employee.remark];
		iStrF.read((char *)buf, employee.remark);
		cout << "REMARK: " << buf << endl;
		delete buf;
		cout << employee.age << endl;
	}
}

Any better solution, i can't found any useful book for the I/O for it.
 
I still cannot get the answer. The problem is, the string size can only be known at runtime, otherwise I can just use the character array (fixed size) to eliminate all the problem. But doing that way will waste up space in the file.
 
std::string binary serialization (unsafe!) variant:
Code:
void StrTo(const std::string& s, std::ostream& f)
{
  int sz = s.size();
  f.write((const char*)&sz,sizeof sz);
  if (sz)
     f.write(s.c_str(),sz);
}

void StrFrom(std::string& s, std::istream& f)
{
  int sz;
  f.read((char*)&sz,sizeof sz);
  if (sz > 0)
  {
     char* p = new char[sz];
     f.read(p,sz);
     s.assign(p,sz);
     delete [] p; // See [] before pointer in delete array.
  }
  else
     s.erase();
}
Add i/o error and EoF handling.
Binary mode stream assumed.
Remember that std::string may contain zero bytes.
 
Use data() instead of c_str(). Change StrFrom to use vector:
Code:
void StrTo(const std::string& s, std::ostream& f)
{
  int sz = s.size();
  f.write((const char*)&sz,sizeof sz);
  if (sz)
     f.write(s.data(),sz);
}

void StrFrom(std::string& s, std::istream& f)
{
  int sz;
  f.read((char*)&sz,sizeof sz);
  if (sz > 0)
  {
     std::vector<char> p(sz);
     f.read(p,sz);
     s.assign(p.begin(),p.end());
  }
  else
     s.erase();
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top