I'm supposed to write a tcp server program which writes into a file a record as structure.
The code is given below:

int n,i;
 cout<<"Enter number of student records";
 cin>>n;
 for(i=0;i<n;i++)
 {
  cout<<"Enter id,name,average mark";
  cin>>r[i].id>>r[i].name>>r[i].mark;
 }
int i,n1;
 FILE *fp;
 FILE *file = fopen("db.dat", "wb"); 
 cout<<"Writing into file\n";
 if ( file != NULL )
 { 
  for(i=0;i<n;i++)
	 fwrite(&r[i], sizeof r[i], 1, file); 
  fclose(file);
 }
 cout<<"Writing completed\n";

There is no problem in writing part(or there is????)
When i read from the file using fread it prints junk values. What is the problem??
Does fread not place correct values in respective variables? If not how to do it??

struct rec re;
fread(&re,sizeof re,1,fp);
 for(i=0;i<n;i++)
 {
  fread(&re,sizeof re,1,fp);
  cout<<re.id<<re.name<<re.mark;
 }

Dani AI

Generated

Quick diagnosis for (and a follow-up to ): the usual causes for “junk” after a binary read are not a mysterious fread bug but one (or more) of these definite problems—the file pointer used for reading was never opened (or was NULL), the read loop/offset is wrong (there’s an extra read before the loop in the snippet), the code is printing a char buffer that isn’t NUL-terminated, or the on-disk layout doesn’t match what the reader assumes (struct padding, pointers, std::string, different write/read order). ’s advice to prefer C++ streams is sound; length-prefixed serialization avoids padding and string-termination traps.

Example (length-prefixed, C++ streams — different approach from the FILE* code shown):

struct Student { int id; double mark; std::string name; };

void writeStudent(std::ofstream &o, const Student &s) {
    uint32_t L = static_cast<uint32_t>(s.name.size());
    o.write(reinterpret_cast<const char*>(&s.id), sizeof(s.id));
    o.write(reinterpret_cast<const char*>(&L), sizeof(L));
    o.write(s.name.data(), L);
    o.write(reinterpret_cast<const char*>(&s.mark), sizeof(s.mark));
}

bool readStudent(std::ifstream &i, Student &s) {
    if (!i.read(reinterpret_cast<char*>(&s.id), sizeof(s.id))) return false;
    uint32_t L;
    if (!i.read(reinterpret_cast<char*>(&L), sizeof(L))) return false;
    s.name.resize(L);
    if (!i.read(&s.name[0], L)) return false;
    if (!i.read(reinterpret_cast<char*>(&s.mark), sizeof(s.mark))) return false;
    return true;
}

Short troubleshooting checklist:

  • Always check that the file opened successfully before any read/write.
  • Don’t mix file variables (the write code used file, the read snippet used fp — confirm fp = fopen("db.dat","rb")).
  • Confirm the same sequence/types are written and read. If writing raw structs, ensure they are POD and stable (or better, avoid raw struct dumps).
  • For fixed char arrays, ensure the source strings are NUL-terminated; prefer std::string + length prefix for robust I/O.
  • To discover how many records exist, use seek/tell (file length / record size) instead of trusting an n that might not match the file.

Following those checks and using the length-prefixed pattern above eliminates the common causes of “junk” output.

If the following doesn't fix the problem then the problem is in the way the data is being input as posted in your first code snippet.

int i,n1;
FILE *file = fopen("db.dat", "wb"); 
cout<<"Writing into file\n";
if ( file != NULL )
{ 
    fwrite(r, sizeof(r[0]), n,file); 
    fclose(file);
}
cout<<"Writing completed\n";

and

struct rec re;
FILE *file = fopen("db.dat", "rb"); 
while( fread(&re,sizeof re,1, file) > 0)
{
  cout<<re.id<<re.name<<re.mark<<'\n';
}

Since this is a c++ program you really should use ofstream and ifstream classes instead of FILE*.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.