Reading and appending from/to a file with std::fstream - c++

I'm wondering why the following piece of code doesn't work, looks pretty straight-forward, am I making a mistake?
The result of this is: file created but empty, if I manually add lines those lines are showed with this code, but nothing else happens.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main(){
fstream mfile("text.txt", ios_base::in | ios_base::out | ios_base::app);
mfile.seekg(ios_base::beg);
string line;
while( getline(mfile,line) ){
std::cout << line << "\n";
}
mfile.seekg(ios_base::end);
mfile << "Line 1\n";
mfile << "Line 2\n";
mfile << "---------------------------------\n";
mfile.seekg(ios_base::beg);
while( getline(mfile,line) ){
std::cout << line << "\n";
}
mfile.seekg(ios_base::end);
}

Couple of things:
When you are ready to write, you need to seekp() rather than seekg(), i.e.
mfile.seekp(ios_base::end);
Now, the problem here is that the getline() calls will set the stream flags (specifically eof), and as a result the stream is not ready for further operations, you need to clear the flags first!
try this:
string line;
mfile.seekg(ios_base::beg);
while( getline(mfile,line) ){
std::cout << line << endl;
}
mfile.seekp(ios_base::end); // seekp
mfile.clear(); // clear any flags
mfile << "Line 1" << endl; // now we're good
mfile << "Line 2" << endl;
mfile << "---------------------------------" << endl;
mfile.seekg(ios_base::beg);
while( getline(mfile,line) ){
std::cout << line << endl;
}
Also, use std::endl rather than "\n", this will trigger a flush of the buffers to the file at the OS's convinience...

Related

Why is Appended content not showing up on reading from a file in C++?

Please look at this code first, then I will ask my question.
#include <bits/stdc++.h>
#include <fstream>
using std::cout;
using std::cin;
using std::endl;
int main() {
std::ofstream out_file ("outfile.txt"); /* creates a outfile.txt */
if (!out_file) { // checks files existence
std::cerr << "Error bruh!" << endl;
return (1);
}
int num = 100;
double total = 456.78;
std::string name = "atik";
out_file << num << "\n" // writing to the file
<< total << "\n"
<< name << endl;
/* Reading from file, because i want to! - */
std::ifstream in_file("outfile.txt"); // will open outfile for reading.
char c;
while (in_file.get(c)) {
cout << c;
}
/*
Output (as expected) -
100
456.78
atik
Right Now My **output.txt** file is - (as expected)
100
456.78
atik
*/
/* Appending the file that we just created - */
std::ofstream out_file2 ("outfile.txt", std::ios::app);
cout << "\nEnter something to write in file : " << endl;
std::string line;
getline(cin, line);
out_file2 << line; // writes to out_file2
/* Reading from file again - */
std::ifstream in_file2("outfile.txt"); // will open outfile.txt for reading.
if( !in_file2 ) {
std::cerr << "File didn't open. Error encountered." << endl;
}
char ch;
cout << endl;
while( in_file2.get(ch) ) {
cout << ch;
}
/*
Output (unexpected? why?)-
100
456.78
atik
*/
in_file.close();
in_file.close();
out_file.close();
out_file2.close();
return 0;
}
Now, my outfile..txt is - (as expected):
100
456.78
atik
Hello there
Then why is the output for in_file2 not showing Hello there? Why does it truncate the Hello there? Can someone please explain?
out_file2<<line;
doesn't flush (the use of std::endl in the prior code does), so if there's less than a full block of data read from std::cin, the data written to out_file2 is likely stuck in your user-mode buffers (and not visible when you open the file for read independently). Those buffers make I/O efficient by reducing the number of system calls when you're performing many smallish writes, in exchange for any buffered data not being visible outside of that file handle until the buffer is flushed (implicitly by filling, or explicitly by manual flushing or closing the file handle).
Simply changing that line to:
out_file2 << line << std::flush;
(or just .close()ing out_file2 once you're done with it) will cause it to flush properly and you should see the new data on opening it again for read.

write a c++program to convert a text file to html file

I am a beginner of c++ and find this question and code online, was trying to make it ok to read not only the file he gave but also any txt file but it shows some problem and I have no idea how to fix
the text file is just like regular text file, not an HTML format txt file
#include <iostream>
#include <fstream>
#include <map>
using namespace std;
istream findParagraph(istream& is, string& word)
{
cout << "<br>" << endl;
}
int main(int argc, char* argv[])
{
argv[1] = "The Republic, by Plato.txt";
ifstream infile(argv[1]);
char ch = 0;
ofstream out("title.html");
out << "<html>" << endl
<< "<head>" << endl
<< "<title>" << argv[1] << "</title>" << endl
<< "</head>" << endl
<< "<body>" << endl;
typedef map<string, unsigned> dictionary_type;
dictionary_type words;
string word;
while (findParagraph(infile, word))
++words[word];
out << "</body>" << endl << "</html>";
} //end main
1>C:\Users\User\source\repos\txt2html\txt2html\txt2html.cpp(15,40): error C2440: '=': cannot convert from 'const char [27]' to 'char *'
You want a basic program that converts a textfile to a minimum html file. You can pass the filename of the text file as parameter to your program.
If the name of your executable program would be "convert", then you can invoke your program with "convert input.txt"
The first parameter that you enter on the command line will appear in argv[1], the 2nd in argv[2] and so on. argv[0] contains the name of the program itself.
So please adapt the handling of the argv parameter. By the way, you could also give the name of the output html file as additional parameter and user argv[2] as output file name. argc would then be 3.
After opening all files and checking for errors, we will first write initial header information to the output html file.
Then we use the std::getline() function to read the source file line by line, until it is completely read.
For each line we read, we will output the plain text to the html file and add a line break "< br >".
At the end, we write the closing tags and that's it.
Please see the attached skelleton example program, which you can use to develop your ideas further.
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
int main(int argc, char *argv[])
{
// Filename is parameter
// Check if program has been invoked with on parameter
if (argc == 2) {
// Parameter is filename. Try to open the input text file
std::ifstream textFile(argv[1]);
// File could be opened
if (textFile) {
// Now open the output file. Becuase, if this cannot be opened then no need to do further steps
std::ofstream htmlFile("title.html");
if (htmlFile) {
// All files are open. Start to build the output
// Start writing the header
htmlFile << "<html>" << '\n' << "<head>" << '\n' <<"<title>" << argv[1] << "</title>" << '\n' << "</head>" <<
"<body>" << '\n';
// Write the body
// Frist read a complete line
std::string line{};
while (std::getline(textFile, line)) {
// Write the line and append a <br>
htmlFile << line << "<br>" << '\n';
}
// End of body
htmlFile << "</body>" << '\n' << "</html>" << '\n';
}
else {
// Error. HTML file could not be opend
std::cerr << "Could not open output HTML file 'title.html'\n";
}
}
else {
// Error. input text file could not be opend
std::cerr << "Could not open input text file '" << argv[1] << "'\n";
}
}
else {
// // Error, program has not been invoked correctly
std::cerr << "Nof Filename given. Invoke this program ("<< argv[0] << ") with 'file name' as parameter\n";
}
return 0;
}

C++ (pre C++11) fstream initialized by sstream

I am trying to open other process stdin and write to it, using C++, no dup() and other C tricks. But unfortunately, fstream constructor taking string seems to be available only from C++11 ( source:http://www.cplusplus.com/reference/fstream/fstream/fstream/ )
#include <iostream>
#include <fstream>
#include <sstream>
//using namespace std;
int main()
{
pid_t pid = fork();
if (pid == 0)
{
// std::cout << "child:" << i << std::endl;
std::string line;
std::cin.sync();
std::cout << "child got message:" << std::endl;
while ( std::getline(std::cin, line) )
{
std::cout << line << std::endl;
}
std::cout << "child done receiving" << std::endl;
}
else{
//std::cout << "parent"<<std::endl;
std::ifstream file("stdin", std::ios::in);
if(file.is_open())
{
std::string tmp, str;
std::stringstream pidstr;
pidstr << "/proc/" << pid << "/fd/0";
while ( std::getline(file, tmp) )
str += tmp + "\n";
std::fstream other( (pidstr.str().c_str()), std::ios::out);
other << str ;
}
}
return 0;
}
I have four questions:
Is "pidstr.str().c_str()" most C++ way to do it? Looks ugly to me.
Is that proper C++ way or maybe there are better alternatives?
Since, as far as I know, getline() is blocking, can I ommit cin.sync(), expecting child to wait for input in while ?
Why do I need to press enter twice, (regardless if i have getchar in child commented out or not(!))
Thanks for understanding.
EDIT: This compiles, and produces desired output, using Code:Blocks, Linux 13.04
EDIT2: No, apparently this does NOT produce desired output. I've added some changes: parent waits for child to exit (not important here).
But also changed this (in child) :
while ( std::getline(std::cin, line) )
{
std::cout << line << std::endl;
}
std::cout << "child done" << std::endl;
to this :
std::getline(std::cin, line);
int lines; // this is single line sent as first from parent, containing int
std::istringstream toint(line);
toint >> lines;
std::cout << "how much lines should it read:" << lines << std::endl;
And it appears that child will wait for anything on stdin, then prints out that what was sent from parent. Really, sometimes I wonder how should i consider C++ as better than plain C :/

File not saving, or not

I cannot seem to figure out why, during the while loop at the bottom,
std::cout << line;
does not print anything.
I believe that the test.txt file is not actually being written to because when I open test.txt in my folder, its empty. Any thoughts?
void Ticket::WriteTicket()
{
std::string ticketInput;
std::ofstream ticketFile("test.txt");
ticketFile.open("test.txt");
std::cout << "Please Enter Ticket Information: " << std::endl;
getline(std::cin, ticketInput);
std::cout << ticketInput << std::endl; //does print out the line
ticketFile << ticketInput;
ticketFile.close();
//here for testing only
std::string line;
std::ifstream ticketRead("test.txt");
while(getline(ticketRead, line));
{
std::cout << "something here?: " << line; // there is nothing here when it outputs
}
}
EDIT (SOLUTION):
After using some of the information that was given above, mainly from Basile Starynkevitch (I put this here because I cannot upvote yet), I was able to get the code to work!
I also did some research in my book and copied a similar program's style. Aka where to put what part of the code, and then the input worked. I continued on with the output and the key part was the std::ifstream::in in the opening of the file for output.
void Ticket::WriteTicket()
{
std::string ticketInput;
std::cout << "Please Enter Ticket Information: " << std::endl;
getline(std::cin, ticketInput);
std::ofstream ticketFile("Ticket.txt");
ticketFile << ticketInput << std::endl;
ticketFile.close();
//here for testing
std::ifstream ticketRead;
ticketRead.open("Ticket.txt", std::ifstream::in);
std::string line;
while(getline(ticketRead, line))
{
std::cout << line << std::endl;
}
}
Thank you for the help everyone!
You need to flush the output buffer.
ticketFile << ticketInput;
should be
ticketFile << ticketInput << std::endl;
std::endl flushes the output buffer.See std::flush if you don't want the new line.
C++ I/O is buffered. At least code
std::cout << "something here?: " << line << std::flush;
but in your case
std::cout << "something here?: " << line << std::endl;
would be better.
Also
std::ofstream ticketFile("test.txt")
should probably be
std::ofstream ticketFile("test.txt", std::ios_base::out);
I strongly suggest taking some hours to read more about C++ libraries before coding. Check every function or class that you are using. Of course, you also need to std::flush on ticketFile.
Maybe the file need to be openned in write mode.
Try this
std::ofstream ticketFile("test.txt","w");

Nicolai Josuttis says in his book that the open member function doesn't clear the state flags. That's not what I found in VS2010. Is this a MS issue?

Nicolai Josuttis in page 547 of his book "The C++ Standard Library" says the following in relation to the code below :
Note that after the processing of a file, clear() must be called to clear the state flags that are set at end-of-file. This is required because the stream object is used for multiple files. The member function open() does not clear the state flags. open() never clears any state flags. Thus, if a stream was not in a good state, after closing and reopening it you still have to call clear() to get to a good state. This is also the case, if you open a different file.
// header files for file I/O
#include <fstream>
#include <iostream>
using namespace std;
/* for all file names passed as command-line arguments
* - open, print contents, and close file
*/
int main (int argc, char* argv[])
{
ifstream file;
// for all command-line arguments
for (int i=1; i<argc; ++i) {
// open file
file.open(argv[i]);
// write file contents to cout
char c;
while (file.get(c)) {
cout.put(c);
}
// clear eofbit and failbit set due to end-of-file
file.clear();
// close file
file.close();
}
}
My code below works without a problem in VS2010. Note that after the file "data.txt" is created, it's read twice without clearing the input stream flags.
#include <iostream>
#include <fstream>
#include <string>
int main()
{
// Create file "data.txt" for writing, write 4 lines into the file and close the file.
std::ofstream out("data.txt");
out << "Line 1" << '\n' << "Line 2" << '\n' << "Line 3" << '\n' << "Line 4" << '\n';
out.close();
// Open the file "data.txt" for reading and write file contents to cout
std::ifstream in("data.txt");
std::string s;
while( std::getline(in, s) ) std::cout << s << '\n';
std::cout << '\n';
std::cout << std::boolalpha << "ifstream.eof() before close - " << in.eof() << '\n';
// Close the file without clearing its flags
in.close();
std::cout << std::boolalpha << "ifstream.eof() after close - " << in.eof() << '\n';
// Open the file "data.txt" again for reading
in.open("data.txt");
std::cout << std::boolalpha << "ifstream.good() after open - " << in.good() << '\n';
std::cout << '\n';
// Read and print the file contents
while( std::getline(in, s) ) std::cout << s << '\n';
std::cout << '\n';
}
Ouput
That was changed for C++11. The C++98 rule (as correctly described by Josuttis) was clearly wrong, so I wouldn't be surprised if implementations didn't honor it.