Is there a way to implicitly flush data to an output stream?
#include <iostream>
#include <fstream>
using namespace std;
#define log logstream
int main()
{
ofstream logstream("test.log");
log << "Test1" << 123 << endl; // explicitly flushed
log << "Test2" << 123; // ?
// Test2 not written, yet...
cout << "Check log file..." << endl;
int tmp;
cin >> tmp;
}
I would like to be able to log without specifying the << endl manipulator every time.
You may use std::unitbuf.
log << std::unitbuf;
And then flush would be done at each insertion.
Related
I've been trying to write a code to read from a file line by line:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream jin("Story.txt");
// ins.open("Story.txt", ios::in);
if (!jin)
{
cout << "File not opened" << endl;
return 1;
}
else{
char a[100];
do
{
jin.getline(a, 100);
cout << a << endl;
}
while (!jin.eof());
jin.close();
return 0;
}
}
However, on executing this program on Visual Studio Code on Windows, it behaves as infinite loop.
Can someone tell what's wrong?
(I am sure that the file Story.txt exists, no doubt about that)
When std::istream::getline has read 100-1 characters (without finding a newline,\n), it will set the failbit on the stream. This prevents further reading on the stream (unless you reset that state). It does however not set eofbit so you are now in a bit of a pickle. The failbit prevents further reading, and eof() returns false, because eofbit is not set - it will therefore loop indefinitely.
If at least one of the lines in Story.txt is longer than 99 chars, the above is what will happen.
The easiest way out is to use a std::string and std::getline instead:
#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::ifstream jin("Story.txt");
if(!jin) {
std::cerr << "File not opened: " << std::strerror(errno) << std::endl;
return 1;
}
std::string a;
while(std::getline(jin, a)) {
std::cout << a << '\n';
}
return 0;
}
If you really do not want to use std::getline and std::string, you can, but it's much harder:
#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>
int main() {
std::ifstream jin("Story.txt");
if(!jin) {
std::cerr << "File not opened: " << std::strerror(errno) << std::endl;
return 1;
}
char a[100];
while(true) {
jin.getline(a, 100);
std::cout << a; // output what we got
if(jin) {
// got a complete line, add a newline to the output
std::cout << '\n';
} else {
// did not get a newline
if(jin.eof()) break; // oh, the end of the file, break out
// reset the failbit to continue reading the long line
jin.clear();
}
}
}
jin.eof() will only return true if a eof-token is found, and this will not happend unless the file is open. That is what causing your infinite loop.
Then you would probably want something like this:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream jin{"Story.txt"};
if (!jin)
{
cout << "File not opened" << endl;
return 1;
}
for (std::string a; std::getline(jin, a);) { // Read every line
cout << a << "\n";
}
// jin is closed when going out of scope so no need for close();
return 0;
}
Suppose I've got code like
#include <iostream>
using namespace std;
int main() {
cout << "Redirect to file1" << endl;
cout << "Redirect to file2" << endl;
return 0;
}
I want to redirect the first output to file1 and the second to file2. Is that possible?
I think in C, fclose(stdout) and reopen the stdout might help but I'm not sure how to reopen it or whether it works.
Thanks
UPDATE: What for?
I have a program A, which reads input from the user and generates corresponding output. Now I want to check whether it is correct, I have a program B which generate input for A, as well as correct output. B will generate one set of test data at a time. And I will have thousands of tests.
On my machine, a thousand times ./B > ``mktemp a.XXX`` works better than using ofstream. Using fstream for thousands of times, my hard drive light flashes crazily. But not when redirecting to temp file.
UPDATE2:
In C++, it seems that the prevailing answer is cout along with cerr.
What about C, apart from stderr, can I close stdout and reopen it?
Why not use file streams ? this way it will most likely work regardless of the shell redirection:
#include <fstream>
#include <fstream>
using namespace std;
// opeen files
ofstream file1 ( "file1");
ofstream file2 ( "file2");
//write
file1 << "Redirect to file1" << endl;
file2 << "Redirect to file2" << endl;
//close files
file1.close();
file2.close();
You can use cout AND cerr.
cout << "Redirect to file1" << endl;
cerr << "Redirect to file2" << endl;
cerr goes to standard error
You can always use the standard error stream for e.g. error messages.
#include <iostream>
using namespace std;
int main() {
cout << "Redirect to file1" << endl;
cerr << "Redirect to file2" << endl;
}
For example, using the Windows [cmd.exe] command interpreter, and the Visual C++ cl compiler:
[D:\dev\test]
> type con >streams.cpp
#include <iostream>
using namespace std;
int main() {
cout << "Redirect to file1" << endl;
cerr << "Redirect to file2" << endl;
}
^Z
[D:\dev\test]
> cl streams.cpp
streams.cpp
[D:\dev\test]
> streams 1>a.txt 2>b.txt
[D:\dev\test]
> type a.txt
Redirect to file1
[D:\dev\test]
> type b.txt
Redirect to file2
[D:\dev\test]
> _
EDIT: added colorized code and boldface emphasis.
Another way doing it is using cout.rdbuf() like this:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream cfile1("test1.txt");
ofstream cfile2("test2.txt");
cout.rdbuf(cfile1.rdbuf());
cout << "Redirect to file1" << endl;
cout.rdbuf(cfile2.rdbuf());
cout << "Redirect to file2" << endl;
return 0;
}
Code:
#include <iostream>
using namespace std;
int main() {
cout << "Redirect to file1" << endl;
cerr << "Redirect to file2" << endl;
return 0;
}
Console:
test > 1.txt 2> 2.txt
1.txt:
Redirect to file1
2.txt:
Redirect to file2
I am trying a reasonably simple program to test binary input/output. I am basically writing a file with a header (string) and some data (doubles). The code is as follows:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
typedef std::ostream_iterator<double> oi_t;
typedef std::istream_iterator<double> ii_t;
std::ofstream ofs("data.bin", std::ios::in);
//-If file doesn't exist, create a new one now
if(!ofs) {
ofs.open("data.bin", std::ios::out|std::ios::binary|std::ios::app);
}
else {
ofs.close();
ofs.open("data.bin", std::ios::out|std::ios::binary|std::ios::app);
}
//-Write a header consisting of length of grid subdomain and its name
///*
const std::string grid = "Header";
unsigned int olen = grid.size();
ofs.write(reinterpret_cast<const char*>(&olen), sizeof(olen));
ofs.write(grid.c_str(), olen);
//*/
//-Now write the data
///*
std::vector<double> data_out;
//std::vector<std::pair<int, int> > cell_ids;
for(int i=0; i<100; ++i) {
data_out.push_back(5.0*double(i) + 100.0);
}
ofs << std::setprecision(4);
std::copy(data_out.begin(), data_out.end(), oi_t(ofs, " "));
//*/
ofs.close();
//-Now read the binary file; first header then data
std::ifstream ifs("data.bin", std::ios::binary);
///*
unsigned int ilen;
ifs.read(reinterpret_cast<char*>(&ilen), sizeof(ilen));
std::string header;
if(ilen > 0) {
char* buf = new char[ilen];
ifs.read(buf,ilen);
header.append(buf,ilen);
delete[] buf;
}
std::cout << "Read header: " << header << "\n";
//*/
///*
std::vector<double> data_in;
ii_t ii(ifs);
std::copy(ii, ii_t(), std::back_inserter(data_in));
std::cout << "Read data size: " << data_in.size() << "\n";
//*/
ifs.close();
//-Check the result
///*
for(int i=0; i < data_out.size(); ++i) {
std::cout << "Testing input/output element #" << i << " : "
<< data_out[i] << " " << data_in[i] << "\n";
}
std::cout << "Element sizes: " << data_out.size() << " " << data_in.size() <<
"\n";
//*/
return 0;
}
The problem is that when I try to write and read (and then print) both the header and the data it fails (I confirmed that it doesn't read the data then, but displays the header correctly). But when I comment out one of the write sections (header and/or data), it displays that part correctly indicating the read worked. I am sure I am not doing the read properly. Perhaps I am missing the usage of seekg somewhere.
The code runs fine for me. However you never check if the file is successfully opened for writing, so it could be silently failing on your system. After you open ofs you should add
if (!ofs) {
std::cout << "Could not open file for writing" << std::endl;
return 1;
}
And the same thing after you open ifs
if (!ifs) {
std::cout << "Could not open file for reading" << std::endl;
return 1;
}
Or something along those lines. Also I do not understand why you check if the file exists first since you do the same whether it exists or not.
This should work
#include <iostream>
using std::cout;
using std::cerr;
using std::cin;
using std::endl;
#include <fstream>
using std::ifstream;
#include <cstdint>
int main() {
ifstream fin;
fin.open("input.dat", std::ios::binary | std::ios::in);
if (!fin) {
cerr << "Cannot open file " << "input.dat" << endl;
exit(1);
}
uint8_t input_byte;
while (fin >> input_byte) {
cout << "got byte " << input_byte << endl;
}
return 0;
}
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...
I have some problems, I'm getting these errors (marked in the code):
identifier "cerr" is undefined
no operator "<<" matches these operands
Why?
#include "basic.h"
#include <fstream>
using namespace std;
int main()
{
ofstream output("output.txt",ios::out);
if (output == NULL)
{
cerr << "File cannot be opened" << endl; // first error here
return 1;
}
output << "Opening of basic account with a 100 Pound deposit: "
<< endl;
Basic myBasic (100);
output << myBasic << endl; // second error here
}
You must include iostream in order to use cerr.
See http://en.cppreference.com/w/cpp/io/basic_ostream.
You need to add this at the top :
#include <iostream>
for cerr and endl
include iostream for cerr support.
And there is no implementation of operator << for class Basic. You'd have to make that implementation yourself. See here.
#include <fstream>
#include <iostream>
#include "basic.h"
std::ostream& operator<<(std::ostream &out, Basic const &x) {
// output stuff: out << x.whatever;
return out;
}
int main() {
using namespace std;
ofstream output ("output.txt", ios::out);
if (!output) { // NOT comparing against NULL
cerr << "File cannot be opened.\n";
return 1;
}
output << "Opening of basic account with a 100 Pound deposit:\n";
Basic myBasic (100);
output << myBasic << endl;
return 0;
}