I have class Writer that has two ofstream members.
Both streams are associated with the same output file. I'd like to use both streams in Writer::write method, but to make sure that each stream writes to the end of the real output file.
Code
class my_ofstream1:
public ofstream
{
// implement some functions.
// using internal, extended type of streambuf
};
class my_ofstream2:
public ofstream
{
// implement some functions.
// using internal, extended type of streambuf
// (not the same type as found in my_ofstream1)
};
class Writer
{
public:
void open(string path)
{
f1.open(path.c_str(),ios_base::out); f2.open(path.c_str(),ios_base::out);
}
void close()
{
f1.close(); f2.close();
}
void write()
{
string s1 = "some string 1";
string s2 = "some string 2";
f1.write(s1.c_str(), s1.size());
// TBD - ensure stream f2 writes to the end of the actual output file
assert(f1.tellp() == f2.tellp());
f2.write(s2.c_str(), s2.size());
}
private:
my_ofstream1 f1;
my_ofstream1 f2;
};
void main()
{
Writer w;
w.open("some_file.txt");
w.write();
w.close();
}
Questions
How to ensure f2 is in sync with f1? meaning, before writing, stream offset of f2 must be in sync with stream offset of f1 and vice versa?
I can't use function std::ios::rdbuf since each ofstream uses special derived streambuf. so by using rdbuf() I'll lose the necessary functionality.
I tried using some of the techniques found in Synchronizing Streams topic but could not make it happen.
This looks like both of your classes use the filtering streambuf
idiom. In any case, don't derive your classes from
std::ofstream, but directly from ostream, and have them both
use the same std::filebuf object. If you are using the
filtering streambuf idiom, don't let your filtering
streambuf's buffer; leave that to the final std::filebuf.
In other words, your "internal, extended type of streambuf"
should contain a pointer to the final sink, which will be
a filebuf (but your filtering streambufs don't need to know
this). Functions like sync, they just pass on to the final
destination, and they should never establish a buffer
themselves, but pass everything on to the filebuf.
Is this not what you are looking for? This could be easily modified to work with ostreams rather the ofstreams, which is nicer - the actual issue is synchronisation of the buffers. In this code I have simply made the filebuf bf unbuffered and it works fine. Alternatively leave it buffered but include calls to pubsync when switching between my_ofstream's. I don't understand why ios:rdbuf is not available. Are you creating your own streambuf?
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;
class my_ofstream1 : public ofstream
{
public:
my_ofstream1& write (const char_type* s, streamsize n)
{
ofstream::write (s, n);
//rdbuf()->pubsync();
return *this;
}
void attach (filebuf* bf){
ios::rdbuf(bf);
}
};
class my_ofstream2 : public ofstream
{
public:
my_ofstream2& write (const char_type* s, streamsize n)
{
ofstream::write (s, n);
//rdbuf()->pubsync();
return *this;
}
void attach (filebuf* bf){
ios::rdbuf(bf);
}
};
class Writer
{
filebuf bf;
my_ofstream1 f1;
my_ofstream1 f2;
public:
void open(string path)
{
bf.open(path.c_str(),ios_base::out);
bf.pubsetbuf(0,0); //unbufferred
f1.attach(&bf); f2.attach(&bf);
}
void close()
{
f1.close(); f2.close();
}
void write()
{
string s1 = "some string 1";
string s2 = "some string 2";
f1.write(s1.c_str(), s1.size());
assert(f1.tellp() == f2.tellp());
f2.write(s2.c_str(), s2.size());
}
};
int main()
{
Writer w;
w.open("some_file.txt");
w.write();
w.close();
return 0;
}
Related
I want to take input from an istream from either a std::ifstream or std::cin depending on some condition.
As far as I can get it working, I had to use a raw std::istream* pointer:
int main(int argc, char const* argv[]) {
std::istream *in_stream;
std::ifstream file;
if (argc > 1) {
std::string filename = argv[1];
file.open(filename);
if (not file.is_open()) {
return -1;
}
in_stream = &file;
} else {
in_stream = &std::cin;
}
// do stuff with the input, regardless of the source...
}
Is there a way to rewrite the above using smart pointers?
This may be a question about ownership: How does one wrap and pass around two different std::istream instances, one of which is owned and needs disposal (which calls close() upon destruction) and ownership transfers, whereas the other one is not owned by user code (e.g. std::cin) and cannot be deleted. The solution is polymorphism: Create an interface like
struct StreamWrapper {
virtual std::istream &stream() = 0;
virtual ~StreamWrapper() = default;
};
and two implementations, e.g. OwnedStreamWrapper and UnownedStreamWrapper. The former can contain a std::istream directly (which is moveable, but not copyable) and the latter can contain (e.g.) a std::istream&, i.e. have no ownership over the referenced stream instance.
struct OwnedStreamWrapper : public StreamWrapper {
template <typename... A>
OwnedStreamWrapper(A &&...a) : stream_{std::forward<A>(a)...} {}
std::istream &stream() override { return stream_; }
private:
std::ifstream stream_;
};
struct UnownedStreamWrapper : public StreamWrapper {
UnownedStreamWrapper(std::istream &stream) : stream_{stream} {}
std::istream &stream() override { return stream_; }
private:
std::istream &stream_;
};
Apart from the stream ownership, wrapper ownership matters as well and can be used either to handle the wrappers’ (and streams’) lifespan automatically on the stack, or to allow a wrapper’s lifespan to exceed that of the current stack frame. In the example below, the first ReadWrapper() takes ownership of the wrapper and deletes it automatically whereas the second ReadWrapper() does not take ownership. In both cases polymorphism (i.e. the implementation of StreamWrapper) determines how the underlying stream is handled, i.e. whether it outlives its wrapper (like std::cin should) or dies together with it (like a manually instantiated stream should).
void ReadWrite(std::istream &in, std::ostream &out) {
std::array<char, 1024> buffer;
while (in) {
in.read(buffer.data(), buffer.size());
out.write(buffer.data(), in.gcount());
}
}
void ReadWrapper(std::unique_ptr<StreamWrapper> stream) {
ReadWrite(stream->stream(), std::cout);
}
void ReadWrapper(StreamWrapper &stream) {
ReadWrite(stream.stream(), std::cout);
}
Below are all four combinations of { owned | unowned } { streams | stream wrappers } in a runnable example:
#include <array>
#include <fstream>
#include <iostream>
#include <memory>
#include <utility>
namespace {
/********** The three snippets above go here! **********/
} // namespace
int main() {
OwnedStreamWrapper stream1{"/proc/cpuinfo"};
std::unique_ptr<StreamWrapper> stream2{
std::make_unique<OwnedStreamWrapper>("/proc/cpuinfo")};
std::ifstream stream3_file{"/proc/cpuinfo"}; // Let’s pretend it is unowned.
UnownedStreamWrapper stream3{stream3_file};
std::ifstream stream4_file{"/proc/cpuinfo"}; // Let’s pretend it is unowned.
std::unique_ptr<StreamWrapper> stream4{
std::make_unique<UnownedStreamWrapper>(stream4_file)};
ReadWrapper(stream1); // owned stream, wrapper kept
ReadWrapper(std::move(stream2)); // owned stream, wrapper transferred
ReadWrapper(stream3); // unowned stream, wrapper kept
ReadWrapper(std::move(stream4)); // unowned stream, wrapper transferred
}
A smart pointer is kind of an awkward fit for this situation, because it requires a dynamic allocation (which is probably not necessary in this case)
1. Do your processing in another function
As #BoP pointed out in the comments a nice way to handle this could be to use another function that gets passed the appropriate input stream:
godbolt
int do_thing(std::istream& in_stream) {
// do stuff with the input, regardless of the source...
int foobar;
in_stream >> foobar;
return 0;
}
int main(int argc, char const* argv[]) {
std::ofstream{"/tmp/foobar"} << 1234;
if(argc > 1) {
std::ifstream file{argv[1]};
if(!file) return -1;
return do_thing(file);
} else {
return do_thing(std::cin);
}
}
2. Switch the stream buffer
If you won't be using std::cin at all if a filename is passed you could change the streambuffer of std::cin to the one of the file with rdbuf() - that way you can use std::cin in both cases.
godbolt
std::ifstream file;
std::streambuf* oldbuf = std::cin.rdbuf();
if (argc > 1) {
file.open(argv[1]);
if (!file) return -1;
// switch buffer of std::cin
std::cin.rdbuf(file.rdbuf());
}
// do stuff with the input, regardless of the source...
int foobar;
std::cin >> foobar; // this will reader either from std::cin or the file, depending on the current streambuffer assigned to std::cin
// restore old stream buffer
std::cin.rdbuf(oldbuf);
3. Using std::unique_ptr / std::shared_ptr with a custom deleter
The easiest solution if you still want to use smart pointers would be to use std::unique_ptr / std::shared_ptr with a custom deleter that handles the std::cin case:
godbolt
// deletes the stream only if it is not std::cin
struct istream_ptr_deleter {
void operator()(std::istream* stream) {
if(&std::cin == stream) return;
delete stream;
}
};
using istream_ptr = std::unique_ptr<std::istream, istream_ptr_deleter>;
// Example Usage:
istream_ptr in_stream;
if (argc > 1) {
in_stream.reset(new std::ifstream(argv[1]));
if (!*in_stream) return -1;
} else {
in_stream.reset(&std::cin);
}
int foobar;
*in_stream >> foobar;
I have currently a function
int myfun(const int a) {
...
return rval;
}
that performs several actions.
I mean to adapt it to write debug information on its behaviour or not according to some parameter that I can pass.
In the cases I want to write that info, I also want to pass the ofstream to use.
And I want applications that were using myfun to still work with no modifications.
So I would ideally change to
int myfun(const int a, ofstream & ofs) {
...
if (!(ofs == NULL)) {
ofs << ...
}
...
if (!(ofs == NULL)) {
ofs << ...
}
return rval;
}
with a default value similar to &ofs=NULL. I know NULL is not appropriate.
What is an appropriate way of handling this?
Note 1:
I could pass an optional parameter with the output file name, but that is less flexible.
Note 2:
I could also change to
int myfun(const int a, const bool debug_info, ofstream & ofs) {
...
if (debug_info) {
ofs << ...
}
with a default value debug_info=false.
I guess this still requires a default value for ofs as above.
Note 3:
The accepted answer in Default ofstream class argument in function proposes an overload without the ofs parameter.
In my case that may not work, as I mean to not write anything when "ofs=NULL".
Note 4:
This other answer apparently works, but it seems somewhat contrived to me, and I am not sure it provides all the same functionality as with passing an ofs.
Related:
Is there a null std::ostream implementation in C++ or libraries?
I want applications that were using myfun to still work with no modifications.
If so, use an ofs with default nullptr
int myfun(const int a, ofstream *ofs = nullptr)
{
if (ofs != nullptr)
{
// (*ofs) << ... ;
}
// ...
}
You can't use a reference parameter ofstream& ofs for such function because a reference cannot be null.
Make an abstract Logger class. It has a method for logging a message. In derived classes you can add logging to file (ofstream) or simply do nothing. You can use any logger, the implementation of myfun() stays the same.
#include <fstream>
class Logger {
public:
virtual void log(const char*) = 0;
};
class NullLogger: public Logger {
public:
void log(const char*) override {};
};
class FileLogger: public Logger {
public:
FileLogger(std::ofstream& s): ofs(s){}
void log(const char* msg) override {
ofs << msg;
}
private:
std::ofstream& ofs;
};
static NullLogger defaultLogger;
int myfun(const int a, Logger& logger=defaultLogger)
{
logger.log("hello");
// ...
logger.log("asdf");
}
int main(){
std::ofstream ofs;
FileLogger fileLogger(ofs);
NullLogger nullLogger;
myfun(10,fileLogger); // logs to file
myfun(10,nullLogger); // logs nothing
myfun(10); // also logs nothing
return 0;
}
In C++17 there is a solution involving std::optional but since it requires default constructible types, std::reference_wrapper has to be used too.
#include <fstream>
#include <optional>
#include <functional>
int myfun(const int a, std::optional<std::reference_wrapper<std::ofstream>> ofs)
{
if (ofs) {
ofs->get() << "...";
return 1;
}
else{
return 0;
}
}
#include <iostream>
int main(){
std::ofstream file;
//Calling is quite nice.
std::cout<<myfun(10,{file})<<'\n'; //Prints 1
std::cout<<myfun(10,{})<<'\n'; //Prints 0
}
The downside of this solution, although idiomatic, is being verbose and heavy on the syntax in some cases.
I would like to define something like a new cout, which I can use to log my data:
some_type cout2( Message_type message ){
cout << message;
logfile.save(message);
}
so I will use it with
cout2 << "some message" << endl;
Up to now I was not able to find out how the code above has to look like exactly.
Thanks for your help.
You can create your own logger like:
class Logger {
public:
Logger(std::string const& filename)
: stream_(filename, std::ofstream::out | std::ofstream::app)
{
if (!stream_) {
// Error...
}
}
Logger& operator<<(std::string const& str) {
std::cout << str;
stream_ << str;
return *this;
}
private:
std::ofstream stream_;
};
Generally speaking, classes from C++ standard library are not designed to be derived, and that is true for stream classes.
So IMHO, it is better to specify what method you will need on your cout2 object, and then:
design a class containing a ostream& object, initialized in ctor
delegate actual output to that internal object
do whatever log you need in your methods
You should use templated a operator << to be able to easily process any class that std::ostream can process.
class LogStream {
std::ostream& out;
Logfile logfile;
LogStream(std::ostream& out, /* param for logfile initialization */ ...)
: out(out), logfile(...) {}
... // other useful methods for state
};
template<typename T>
LogStream& operator << (LogStream& out, T val) {
out.out << message;
// should first test whether T is manipulator, and choose whether and how it should be logged
logfile.save(message);
}
You don't want to modify std::cout.
Instead, you want to create a specialised std::streambuf that writes to two buffers rather than one. For example;
#include <streambuf>
template <typename char_type,
typename traits = std::char_traits<char_type> >
class basic_teebuf:
public std::basic_streambuf<char_type, traits>
{
public:
typedef typename traits::int_type int_type;
basic_teebuf(std::basic_streambuf<char_type, traits> * sb1,
std::basic_streambuf<char_type, traits> * sb2)
: sb1(sb1)
, sb2(sb2)
{
}
protected: // override virtuals inherited from std::basic_streambuf
virtual int sync()
{
int const r1 = sb1->pubsync();
int const r2 = sb2->pubsync();
return r1 == 0 && r2 == 0 ? 0 : -1;
}
virtual int_type overflow(int_type c)
{
int_type const eof = traits::eof();
if (traits::eq_int_type(c, eof))
{
return traits::not_eof(c);
}
else
{
char_type const ch = traits::to_char_type(c);
int_type const r1 = sb1->sputc(ch);
int_type const r2 = sb2->sputc(ch);
return
traits::eq_int_type(r1, eof) ||
traits::eq_int_type(r2, eof) ? eof : c;
}
}
private:
std::basic_streambuf<char_type, traits> * sb1;
std::basic_streambuf<char_type, traits> * sb2;
};
typedef basic_teebuf<char> teebuf;
Then you need to create a specialised ostream which uses such a buffer
#include <ostream>
class teestream : public std::ostream
{
public:
// Construct an ostream which tees output to the supplied
// ostreams.
teestream(std::ostream & o1, std::ostream & o2);
private:
teebuf tbuf;
};
teestream::teestream(std::ostream & o1, std::ostream & o2)
: std::ostream(&tbuf)
, tbuf(o1.rdbuf(), o2.rdbuf())
{
}
All the above does is create a specialised std::ostream that uses our specialised buffer, which in turn makes use of two buffers.
Now, our teestream needs to be initialised using two streams. For example
#include <fstream>
#include <iostream>
// include the preceding definition of teestream here
int main()
{
std::ofstream logfile("hello-world.log");
teestream tee(std::cout, logfile);
// tee is now a stream that writes the same output to std::cout and logfile
tee << "Hello, world!\n";
return 0;
}
The advantage of this is that all stream insertions (operator <<) will work with our teestream - even for classes with overloaded versions.
When main() returns, the streams will also be closed cleanly.
I've written the specalised streambuf as a template (std::streambuf is a specialisation of a templated class named std::basic_streambuf). For generality, it would probably be better to do the same with the stream (using the fact that std::ostream is also a specialisation of a templated std::basic_ostream). I leave that sort of generalisation as an exercise.
The logging systems I've seen, built on this idea look something like this:
#define MY_PRINT(x, ...) \
{ \
fprintf(logFile, x, ##__VA_ARGS__); \
fflush(acuLogFile); \
}
And you would use it like:
MY_PRINT("this is just a test\n");
Even though this is the C way of doing things, it is very versatile and work in C++ as well.
You just have to use your newly define print function everywhere in the code.
Maybe you should have an instance based logger with a .log() method, that, depending on implementation can log to file, write to stdout etc, rather than trying to overload free functions from std namespace?
Your intent will be clearer and it will be more object orientated.
In fact here is an example of a pretty cookie-cutter event logger I wrote recently, if that helps you to understand the sort of thing I'm talking about. My design allows for dependnacy injection, as well as keeping boring decisions about how something should be formatted as output and where it should go (stdout or file etc) in the logger.
Of course you can define your own cout.
First you need a class which can handle the << operator and contains an fstream and an ostream (like cout).
class logstream
{
private:
fstream *filestream;
ostream *cout;
public:
logstream(fstream* filestream, ostream* cout)
{
this->cout = cout;
this->filestream = filestream;
}
string operator<< (char* s)
{
*cout << s;
*filestream << s;
return s;
}
};
To use this, simply initialize it with cout and a fstream.
fstream lout = fstream("Filename", ios::app);
logstream cout = logstream(&lout, &std::cout);
And now you have what you wanted.
cout << "message";
EDIT: Don't forget to include
#include <iostream>
#include <fstream>
and
using namespace std;
I have a std::basic_streambuf subclass that causes all output to be written in uppercase, like this:
class upper_streambuf : public std::streambuf
{
public:
upper_streambuf(std::streambuf &real)
: m_realBuffer(real)
{
}
protected:
virtual int overflow(int c)
{
int uc = std::toupper(c);
m_realBuffer.sputc(uc);
return uc;
}
private:
std::streambuf &m_realBuffer;
};
I use it like this for example (which seems to work OK):
upper_streambuf buf(*std::cout.rdbuf());
std::ostream ucout(&buf);
ucout << "Hello, world!" << std::endl; // prints "HELLO, WORLD!"
What I want to achieve is the more-or-less the inverse, I want to read from a stream and have all input converted to lowercase. I have the following:
class lower_streambuf : public std::streambuf
{
public:
lower_streambuf(std::streambuf &real)
: m_realBuffer(real)
{
}
protected:
virtual int underflow()
{
return std::tolower(m_realBuffer.sbumpc());
}
private:
std::streambuf &m_realBuffer;
};
However, when I try and use this one like this:
lower_streambuf buf(*std::cin.rdbuf());
std::istream lcin(&buf);
std::string line;
std::getline(lcin, line);
The result is a segmentation fault. Am I overriding or calling the wrong functions? Please note I am somewhat of a novice in C++. Please also note that I understand I can read the input completely and simply convert it to lowercase once it has been read, but this is more for learning/academic purposes rather than anything practical.
underflow() has post-conditions that you failed to establish: by the time you return from it, you need to have a get area in your streambuf that holds that character you're returning.
A single-character buffer is sufficient:
protected:
virtual int underflow()
{
ch = std::tolower(m_realBuffer.sbumpc());
+ setg(&ch, &ch, &ch+1);
return ch;
}
private:
+ char ch; // input buffer!
std::streambuf &m_realBuffer;
};
MathWorks currently doesn't allow you to use cout from a mex file when the MATLAB desktop is open because they have redirected stdout. Their current workaround is providing a function, mexPrintf, that they request you use instead. After googling around a bit, I think that it's possible to extend the std::stringbuf class to do what I need. Here's what I have so far. Is this robust enough, or are there other methods I need to overload or a better way to do this? (Looking for portability in a general UNIX environment and the ability to use std::cout as normal if this code is not linked against a mex executable)
class mstream : public stringbuf {
public:
virtual streamsize xsputn(const char *s, std::streamsize n)
{
mexPrintf("*s",s,n);
return basic_streambuf<char, std::char_traits<char>>::xsputn(s,n);
}
};
mstream mout;
outbuf = cout.rdbuf(mout.rdbuf());
You don't really want to overload std::stringbuf, you want to overload std::streambuf or std::basic_streambuf (if you want to support multiple character types), also you need to override the overflow method as well.
But I also think you need to rethink your solution to your problem.
cout is just an ostream, so if all classes / functions takes an ostream then you can pass in anything you like. e.g. cout, ofstream, etc
If that's too hard then I would create my own version of cout, maybe called mycout that can be defined at either compiler time or runtime time (depending on what you want to do).
A simple solution may be:
#include <streambuf>
#include <ostream>
class mystream : public std::streambuf
{
public:
mystream() {}
protected:
virtual int_type overflow(int_type c)
{
if(c != EOF)
{
char z = c;
mexPrintf("%c",c);
return EOF;
}
return c;
}
virtual std::streamsize xsputn(const char* s, std::streamsize num)
{
mexPrintf("*s",s,n);
return num;
}
};
class myostream : public std::ostream
{
protected:
mystream buf;
public:
myostream() : std::ostream(&buf) {}
};
myostream mycout;
And the cout version could just be:
typedef std::cout mycout;
A runtime version is a bit more work but easily doable.
Shane, thanks very much for your help. Here's my final working implementation.
class mstream : public std::streambuf {
public:
protected:
virtual std::streamsize xsputn(const char *s, std::streamsize n);
virtual int overflow(int c = EOF);
};
...
std::streamsize
mstream::xsputn(const char *s, std::streamsize n)
{
mexPrintf("%.*s",n,s);
return n;
}
int
mstream::overflow(int c)
{
if (c != EOF) {
mexPrintf("%.1s",&c);
}
return 1;
}
...
// Replace the std stream with the 'matlab' stream
// Put this in the beginning of the mex function
mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout);
...
// Restore the std stream buffer
std::cout.rdbuf(outbuf);
I have changed the OP's final implementation a little bit, adding a constructor and destructor. Creating an object of this class automatically replaces the stream buffer in std::cout, and when the object goes out of scope, the original stream buffer is restored. RAII!
class mxstreambuf : public std::streambuf {
public:
mxstreambuf() {
stdoutbuf = std::cout.rdbuf( this );
}
~mxstreambuf() {
std::cout.rdbuf( stdoutbuf );
}
protected:
virtual std::streamsize xsputn( const char* s, std::streamsize n ) override {
mexPrintf( "%.*s", n, s );
return n;
}
virtual int overflow( int c = EOF ) override {
if( c != EOF ) {
mexPrintf( "%.1s", & c );
}
return 1;
}
private:
std::streambuf *stdoutbuf;
};
To use the stream buffer in a MEX-file, simply:
mxstreambuf mout;
std::cout << "Hello World!\n";
... and don't worry about forgetting anything.
cout is a particular character output stream. If you want a cout that writes to a file, use an fstream, particularly an ofstream. They have the same interface that cout provides. Additionally, if you want to grab their buffer (with rdbuf) you can.