Reputation: 23
I am learning about how to write records on file and read it .
I created a class called student
, the class has function like enterStudent
, showStudent
, printInsideFile
(student info) ,...... .
when I try to write student info into the file , it works .
when I try to read all student info from the file , it works
when I try to do both , something unexpected happens (nothing show up)
i thought that the problem with file.flush()
, so when i deleted it the output was unreadable text
i could close the file and open it again but i think that is silly
the code is:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class student {
private:
char id[5], name[20], age[5], address[50], gender[5];
public:
void enterStudent() {
cout << "Enter student id : "; cin >> id;
cout << "\nEnter student name : "; cin >> name;
cout << "\nEnter student age : "; cin >> age;
cout << "\nEnter student address : "; cin >> address;
cout << "\nEnter student gender : "; cin >> gender;
}
void showStudent() {
cout << "#########student data##########\n";
cout << "student id : "<< id;
cout << "\nstudent name : " << name;
cout << "\nstudent age : " << age;
cout << "\nstudent address : " << address;
cout << "\nstudent gender : " << gender<<endl;
}
void printInsideFile(fstream &file) {
file.write(id,sizeof(id));
file.write(name, sizeof(name));
file.write(age, sizeof(age));
file.write(address, sizeof(address));
file.write(gender, sizeof(gender));
file.flush();
}
bool readFromFile(fstream &file) {
if (file.eof())
return 0;
file.read(id, sizeof(id));
file.read(name, sizeof(name));
file.read(age, sizeof(age));
file.read(address, sizeof(address));
file.read(gender, sizeof(gender));
if (file.eof())
return 0;
return 1;
}
void showAllFromFile(fstream &file) {
while (this->readFromFile(file))
this->showStudent();
}
};
int main() {
student s;
fstream file;
file.open("a.txt", ios::in | ios::out | ios::app);
if (!file)
goto k270;
s.enterStudent();
s.printInsideFile(file);
//when i read one student , it works okay
//s.readFromFile(file);
//s.showStudent();
//when i try to read multiple students , it doesn't work at all
s.showAllFromFile(file);
file.close();
k270:
system("pause");
return 0;
}
Upvotes: 1
Views: 462
Reputation: 23
The problem was not the ios::app
It seems that functions file.write()
and file.read()
change either reading pointer and writing pointer .
Even if you use file<<"text";
or file>>array of chars;
both of pointers are changing .
I searched about it but didn't find explanation but i find the code of ostream::write and istream::read ,they were advanced so if anybody check the link and tell us why
note that ,when the reading pointer points at the end of the file , it will print out nothing
Upvotes: 1
Reputation: 20141
Considering that I have least experience with std::ios::app, I became curious to find out how it actually works.
I made the following MCVE on coliru which (I believe) is working as expected by the OP:
#include <fstream>
#include <iostream>
int main()
{
// open a text file
std::fstream file("test.txt", std::ios::in | std::ios::out | std::ios::app);
// remember current position of read head
file.seekg(0, std::fstream::end); // a trick to update the read head before writing anything
std::fstream::pos_type pos0 = file.tellg();
std::cout << "pos0: " << pos0 << '\n';
// write a line to end of text
std::cout << "Write a line.\n";
file << "A line written by main.cpp" << std::endl;
std::cout << "pos after writing: " << file.tellg() << '\n';
// rewind to remembered position of read head
file.seekg(pos0);
// read the last written line
{ std::string buffer; std::getline(file, buffer);
std::cout << "Last line: '" << buffer << "'\n";
}
// rewind to the beginning of file
file.seekg(0);
// read all
std::cout << "Read all:\n";
for (std::string buffer; std::getline(file, buffer);) {
std::cout << "'" << buffer << "'\n";
}
}
Test Session:
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp \
&& echo -e "1st line written by echo\n2nd line written by echo\n3rd line written by echo" > test.txt \
; ./a.out
pos0: 75
Write a line.
pos after writing: 102
Last line: 'A line written by main.cpp'
Read all:
'1st line written by echo'
'2nd line written by echo'
'3rd line written by echo'
'A line written by main.cpp'
Notes:
I was fully sure about the file.seekg(0)
which is needed before read all
to rewind the read file head to the begin of file.
I was not sure about the read the last written line
…
I found that the file.seekg(pos0);
is necessary.
Obviously, the previous write seems to touch the write head (of course) as well as the read head.
I had some trouble to retrieve the proper read head position using std::istream::tellg().
It returned the expected value after the first file output but not before.
My last resort was a file.seekg(0, std::fstream::end);
to move the read head to end of file before anything is written.
I apologize for the total lack of any error checking in the example.
Of course, this has to be added in a serious application.
I left it out to keep the sample code as minimal as possible.
Additionally, I didn't consider the error handling a problem in OPs sample code.
Upvotes: 1