#include <iostream>
#include <fstream>
using namespace std;
void foo(){
streambuf *psbuf;
ofstream filestr;
filestr.open ("test.txt");
psbuf = filestr.rdbuf();
cout.rdbuf(psbuf);
}
int main () {
foo();
cout << "This is written to the file";
return 0;
}
Does cout write to the given file?
If not, is there a way to do it without sending the variables to foo, like new?
update :
I can't use a solution that uses class or uses global so plz can some
give me solution that use new. Also passing the from main to foo
streambuf *psbuf;
ofstream filestr;
should work right?
I am trying to do this but its not working?
I pass the stream to foo so it exist in the main so it wont end when foo finish.
void foo(streambuf *psbuf){
ofstream filestr;
filestr.open ("test.txt");
psbuf = filestr.rdbuf();
cout.rdbuf(psbuf);
}
int main () {
streambuf *psbuf
foo(psbuf);
cout << "This is written to the file";
return 0;
}
I suspect that by now compiled and run your code and found that you get a segmentation fault.
You are getting this because you create and open an ofstream object within foo(), which is then destroyed (and closed) at the end of foo. When you attempt to write to the stream in main(), you attempt to access a buffer which no longer exists.
One workaround to this is to make your filestr object global. There are plenty of better ones!
Edit: Here is a better solution as suggested by #MSalters:
#include <iostream>
#include <fstream>
class scoped_cout_redirector
{
public:
scoped_cout_redirector(const std::string& filename)
:backup_(std::cout.rdbuf())
,filestr_(filename.c_str())
,sbuf_(filestr_.rdbuf())
{
std::cout.rdbuf(sbuf_);
}
~scoped_cout_redirector()
{
std::cout.rdbuf(backup_);
}
private:
scoped_cout_redirector();
scoped_cout_redirector(const scoped_cout_redirector& copy);
scoped_cout_redirector& operator =(const scoped_cout_redirector& assign);
std::streambuf* backup_;
std::ofstream filestr_;
std::streambuf* sbuf_;
};
int main()
{
{
scoped_cout_redirector file1("file1.txt");
std::cout << "This is written to the first file." << std::endl;
}
std::cout << "This is written to stdout." << std::endl;
{
scoped_cout_redirector file2("file2.txt");
std::cout << "This is written to the second file." << std::endl;
}
return 0;
}
It seems to me that your code should work but ... Why don't you try yourself ? You will see if everything is written in test.txt or not.
Related
I want to be notified when a file associated with a std::istream is read from using the istream and the same with an ostream being written to. With this in mind I decided to try deriving my own std::basic_filebuf, and just to experiment I tried to override the xsgetn() and xsputn() functions so that they would output to the console before calling the parent implementation:
#include <iostream>
#include <fstream>
#include <cstdio>
class MyFileBuff : public std::filebuf
{
public:
std::streamsize xsgetn(char_type* s, std::streamsize count) override
{
std::cout << "using my xsgetn()" << std::endl;
return std::filebuf::xsgetn(s, count);
}
std::streamsize xsputn(const char_type* s, std::streamsize count) override
{
std::cout << "using my xsputn()" << std::endl;
return std::filebuf::xsputn(s, count);
}
using std::filebuf::basic_filebuf;
};
int main()
{
//open file
FILE* filePtr{ nullptr };
fopen_s(&filePtr, "text.txt", "w+");
//associate file with instance of custom std:filebuff
MyFileBuff fileBuff(filePtr);
//initalize i/o streams with file buffer
std::istream myIStream(&fileBuff);
std::ostream myOStream(&fileBuff);
//output to file
myOStream << "hello world" << std::endl;
const short buffSize{ 1024 };
char buff[buffSize];
myIStream.seekg(0);
//read from file
myIStream.getline(buff, buffSize);
//output what was read to console
std::cout << buff << std::endl;
return 0;
}
This outputs:
> using my xsputn()
> hello world
As you can see, my override of xsputn() is called on the write operation. But despite the read operation completing successfully, my override of xsgetn() is never called. I would like help understanding why.
I have also tried overloading the std::basic_filebuf::uflow() and std::basic_filebuf::underflow() functions in a similar manner and they do successfully output to the console when the istream is read, but I don't understand why xsgetn() never gets called?
In my program I use an external function which generates output to me and I don't want it not to be generated by that function alone,
it's possible?
int main()
{
int a;
//I don't want the output of this function
a = function();
//now i want output
cout << "the result is : " << a;
}
Is it possible?
EDIT:
The function is in an external library.
Using only standard C++ where no dup-like functions exist, you could open a temporary std::FILE and std::swap with stdout.
#include <cerrno>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <sstream>
// extern "C" int function(); // an assumption
// A helper class to temporarilly redirect the output to stdout to a file and to read
// the content of the file afterwards.
class BufferStdout {
public:
// the collector string is used for collecting the output to stdout
BufferStdout (std::string& collector) :
m_collector(collector),
fp(std::fopen("output.txt", "w"))
{
if(fp == nullptr) throw std::runtime_error(std::strerror(errno));
std::swap(stdout, fp); // swap stdout and the temp file
}
~BufferStdout () {
std::swap(stdout, fp); // swap back
std::fclose(fp);
// read the content of the temp file into m_collector
if(std::ifstream is("output.txt"); is) {
m_collector.append(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>{});
}
std::remove("output.txt"); // cleanup
}
private:
std::string& m_collector;
std::FILE* fp;
};
int main() {
std::string collector; // the string that will contain the output from function()
int a;
{
BufferStdout foo(collector);
a = function();
}
std::cout << "the result is : " << a << '\n';
std::cout << "Collected from function():\n";
std::cout << collector << '\n';
}
Yes it is generally possible but a bit complicated, a similar question is in Suppress output to cout from linked library
In addition to you can redirect stdout before invoking the shared library function and then redirect it again after the use of the shared library function in the however this is also a suboptimal solution. Best solution would be to adapt the shared library
// Cpp program to redirect cout to a file
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
fstream file;
file.open("cout.txt", ios::out);
string line;
// Backup streambuffers of cout
streambuf* stream_buffer_cout = cout.rdbuf();
streambuf* stream_buffer_cin = cin.rdbuf();
// Get the streambuffer of the file
streambuf* stream_buffer_file = file.rdbuf();
// Redirect cout to file
cout.rdbuf(stream_buffer_file);
cout << "This line written to file" << endl;
// Redirect cout back to screen
cout.rdbuf(stream_buffer_cout);
cout << "This line is written to screen" << endl;
file.close();
return 0;
}
Note: The above steps can be condensed into a single step
auto cout_buf = cout.rdbuf(file.rdbuf())
// sets couts streambuffer and returns the old
streambuffer back to cout_buf
source : https://www.geeksforgeeks.org/io-redirection-c/
use
fclose(stdout);
with this function you will suppress any printf inside your libraries.
Of course you can not print other stuff inside your software.
I want to output "a" to the file in the function, how do I do it? The following gives me error.
#include <iostream>
#include <fstream>
using namespace std;
void outputfile(const char* file);
int main()
{
int a = 1;
ofstream cc;
cc.open("123.txt");
if (cc.fail())
{
cout << "\nError in file opening" << endl;
return(1);
}
outputfile("123.txt");
cc.close();
return 0;
}
void outputfile(const char* file)
{
// I want to output a to the file, how can I do it? The following gives me error.
file << a;
}
The problem is solved, thanks for answering the question.:)
I see couple of issues that need to be addressed.
You can either pass the name of the file to outputfile or the ofstream. If you pass the name of the file to outputfile, the file needs to be opened in outputfile, not in main.
There are pros and cons to the two approaches. If the name of the file is passed to outputfile, main becomes very simple. However, if the ofstream object needs to be used to make other function calls, it will be better to pass an ofstream as the argument to outputfile.
If a ofstream is passed to outputfile, outputfile becomes very simple. However, if the ofstream is not going to be used by main for anything else, it is better to leave the details of what mechanism used by outputfile to write the data out. outputfile can even resort to FILE* and fprintf without affecting main.
a needs to be made available to outputfile. It can be made a global variable or be passed to outputfile. It is better to avoid global data. Hence, prefer to pass it as an argument.
Solution 1
Pass an ofstream to outputfile, in addition to a.
#include <iostream>
#include <fstream>
using namespace std;
void outputfile(std::ofstream& file, int a);
int main()
{
int a = 1;
ofstream cc;
cc.open("123.txt");
if (cc.fail())
{
cout << "\nError in file opening" << endl;
return(1);
}
outputfile(cc, a);
// No need. The file will be closed when the function returns.
// cc.close();
return 0;
}
void outputfile(std::ofstream& file, int a)
{
file << a;
}
Solution 2
The details of opening and closing the file is left to outputfile. Here, outputfile uses ofstream.
#include <iostream>
#include <fstream>
using namespace std;
void outputfile(char const* file, int a);
int main()
{
int a = 1;
outputfile("123.txt", a);
return 0;
}
void outputfile(char const* file, int a)
{
ofstream cc(file);
if (cc.fail())
{
cout << "\nError in file opening" << endl;
return;
}
cc << a;
}
Solution 3
The details of opening and closing the file is left to outputfile. Here, outputfile uses FILE*.
#include <iostream>
#include <fstream>
using namespace std;
void outputfile(char const* file, int a);
int main()
{
int a = 1;
outputfile("123.txt", a);
return 0;
}
void outputfile(char const* file, int a)
{
FILE* fp = fopen(file, "w");
if ( fp == NULL )
{
cout << "\nError in file opening" << endl;
return;
}
fprintf(fp, "%d", a);
fclose(fp);
}
At first, you have declared a in main(). Either you have to pass it as parameter or you have to take it global. I took global in the code below.
Then what do you do passing const char*? You have to write in file, so send the stream instead like below:
#include <iostream>
#include <fstream>
using namespace std;
void outputfile(ofstream &file); int a=1;
int main() {
ofstream cc;
cc.open("123.txt");
if (cc.fail()) {
cout <<"\nError in file opening" << endl;
return(1);
}
outputfile(cc);
cc.close();
return 0;
}
void outputfile(ofstream &file)
{
// I want to output a to the file, how do I do it? The following gives me error.
file << a;
}
a isn't in scope. Either declare it outside of main() in global space, or pass it into outputfile, something like:
void outputfile(ofstream &file file, int a) {
file << a;
}
can anyone tell me what's wrong with this?
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
class writeManager
{
std::vector<double> valueVector;
std::ofstream ofsFile;
public:
writeManager(void);
void writeOnFile(int);
void openOfsStreams(void);
void closeOfsStreams(void);
};
writeManager::writeManager(void)
{
openOfsStreams();
ofsFile << "FIRST LINE" << std::endl;
closeOfsStreams();
}
void writeManager::writeOnFile(int input)
{
openOfsStreams();
if(ofsFile.good())
{
ofsFile << input << std::endl;
}
else
{
std::cout << "Hey!" << std::endl;
}
ofsFile.close();
}
void writeManager::openOfsStreams(void)
{
ofsFile.open("/home/user/example.txt");
}
void writeManager::closeOfsStreams(void)
{
ofsFile.close();
}
int main()
{
writeManager writeObject;
for (unsigned int i = 0; i!= 5; i++)
{
writeObject.writeOnFile(i);
}
}
I'd like to see this output on file "example.txt"
FIRST LINE
0
1
2
3
4
but I get only
4
PS: no "Hey!" is printed.
The problem is that you open and close the file multiple times and each time you open the file you destroy the contents that were there previously.
Probably you should open the file once only in the constructor (and don't close the file there).
An alternative would be to open the file in 'append' mode, but that would be very inefficient, opening a file is an expensive operation. As Liho suggested
ofsFile.open("/home/user/example.txt", std::ofstream::out | std::ofstream::app);
When you open your ofstream multiple times, it always rewrites it from the beginning.
One of the possible solutions would be to use app flag, i.e. change:
ofsFile.open("/home/user/example.txt");
to
ofsFile.open("/home/user/example.txt", std::ofstream::out | std::ofstream::app);
Yet even better would be to open this ofstream just once in constructor and close it in destructor.
I have a requirement, I need to use printf and cout to display the data into console and file as well.
For printf I have done it but for cout I am struggling, how to do it?
#ifdef _MSC_VER
#define GWEN_FNULL "NUL"
#define va_copy(d,s) ((d) = (s))
#else
#define GWEN_FNULL "/dev/null"
#endif
#include <iostream>
#include <fstream>
using namespace std;
void printf (FILE * outfile, const char * format, ...)
{
va_list ap1, ap2;
int i = 5;
va_start(ap1, format);
va_copy(ap2, ap1);
vprintf(format, ap1);
vfprintf(outfile, format, ap2);
va_end(ap2);
va_end(ap1);
}
/* void COUT(const char* fmt, ...)
{
ofstream out("output-file.txt");
std::cout << "Cout to file";
out << "Cout to file";
}*/
int main (int argc, char *argv[]) {
FILE *outfile;
char *mode = "a+";
char outputFilename[] = "PRINT.log";
outfile = fopen(outputFilename, mode);
char bigfoot[] = "Hello
World!\n";
int howbad = 10;
printf(outfile, "\n--------\n");
//myout();
/* then i realized that i can't send the arguments to fn:PRINTs */
printf(outfile, "%s %i",bigfoot, howbad); /* error here! I can't send bigfoot and howbad*/
system("pause");
return 0;
}
I have done it in COUT(caps, the commented part for the code above) . But I want to use normal std::cout, so how can I override it. And it should work for both sting and variables like
int i = 5;
cout << "Hello world" << i <<endl;
Or are there anyway to capture stdout data, so that they can be easily written into file and console as well.
If you have another stream buffer, you can just replace std::cout's:
std::cout.rdbuf(some_other_rdbuf);
See http://en.cppreference.com/w/cpp/io/basic_ios/rdbuf.
You can swap the underlying buffers. Here is that done facilitated through RAII.
#include <streambuf>
class buffer_restore
{
std::ostream& os;
std::streambuf* buf;
public:
buffer_restore(std::ostream& os) : os(os), buf(os.rdbuf())
{ }
~buffer_restore()
{
os.rdbuf(buf);
}
};
int main()
{
buffer_restore b(std::cout);
std::ofstream file("file.txt");
std::cout.rdbuf(file.rdbuf());
// ...
}
Overriding the behaviour of std::cout is a really bad idea as other developers will have a hard time understanding that the use of std::cout doesn't behave as usual.
Make your intention clear with a simple class
#include <fstream>
#include <iostream>
class DualStream
{
std::ofstream file_stream;
bool valid_state;
public:
DualStream(const char* filename) // the ofstream needs a path
:
file_stream(filename), // open the file stream
valid_state(file_stream) // set the state of the DualStream according to the state of the ofstream
{
}
explicit operator bool() const
{
return valid_state;
}
template <typename T>
DualStream& operator<<(T&& t) // provide a generic operator<<
{
if ( !valid_state ) // if it previously was in a bad state, don't try anything
{
return *this;
}
if ( !(std::cout << t) ) // to console!
{
valid_state = false;
return *this;
}
if ( !(file_stream << t) ) // to file!
{
valid_state = false;
return *this;
}
return *this;
}
};
// let's test it:
int main()
{
DualStream ds("testfile");
if ( (ds << 1 << "\n" << 2 << "\n") )
{
std::cerr << "all went fine\n";
}
else
{
std::cerr << "bad bad stream\n";
}
}
This provides a clean interface and outputs the same for both the console and the file.
You may want to add a flush method or open the file in append mode.
I assume you have some code using std::cout and printf which you cannot modify, otherwise the most simple way to solve your problem would be to write to a different stream from cout and use fprintf rather than or in conjunction with printf.
By following that approach you could define both a new stream class that actually wrote both to standard output and to a given file, as well as a function that combined calls to both printf and fprintf.
However a much simpler approach is to use the tee program, originally from UNIX, which copies its input both to output and to a given file. With that you could simply call your program in this way:
your_program | tee your_log_file
Answers to this question lead to a few alternative implementations available for Windows. Personally I always install cygwin on my PC's to have UNIX/Linux utilities available.
If i guess correctly you want to log everything that goes to the output also into a file.
What you want is an observer pattern.
Replace all direct logging in your code with calls to a new relay.
The logging relay sends your messages to the observers.
One of your observers loggs the message to the screen.
The other one loggs to the file.
Avoid making your relay a singleton if possible.
This suggestion only works if you can edit all of your source files.
std::cout writes to stdout file you can do the following on Linux and Windows
#include <stdio.h>
#include <iostream>
int main()
{
freopen("test.txt", "w", stdout);
std::cout << "Hello strange stdout\n";
}
to change it back use the following taken from here
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
FILE *stream ;
if((stream = freopen("file.txt", "w", stdout)) == NULL)
exit(-1);
printf("this is stdout output\n");
stream = freopen("CON", "w", stdout);
printf("And now back to the console once again\n");
}
Note: The latter is windows only
cout is normally implemented as an object instance so you can't override it in the way that you would overload / override a function or a class.
Your best bet is not to fight that - yes you could build a my_cout and #define cout my_cout but that would make your code obtuse.
For readability I'd leave cout as it is. It's a standard and everyone knows what it can and can't do.
Try using a macro - something like this (you'll need to add the includes) :
#define MY_COUT(theos,printThis) { cout << printThis ; theos << printThis; }
void test()
{
ofstream myos;
myos.open("testfile", ios::trunc|ios::out);
int i = 7;
MY_COUT(myos, "try this numbers" << i << i + 1 << endl);
myos.close()
}
There's already a Boost class for this: tee