I need to check whether a std::fstream opened a file in read and/or write mode.
So far, I found iosbase::openmode, but I don't think I can access it.
Is there any other way?
The file streams do not store any information about how they are opened and, correspondingly, can't be queried for the mode they are in. The background is that information isn't needed by the stream implementation itself and it would require to store unnecessary data. Also, when using a stream it is normally clear whether it is read or written: the operations are substantially different that the use indicates which operation is used.
If you really need to get this information, I'd recommend creating a stream type which sets up an std::iostream upon construction using a std::filebuf and stores the information in a pword() so the information can be recovered while passing the stream as std::iostream. The basics could look something like this:
#include <fstream>
#include <iostream>
struct astream_base {
astream_base(std::string const& name, std::ios_base::openmode mode)
: d_sbuf() {
this->d_sbuf.open(name.c_str(), mode);
}
std::filebuf d_sbuf;
};
std::ios_base::openmode mode(std::iostream& stream);
class astream
: private virtual astream_base
, public std::iostream
{
static int index() { static int rc = std::ios_base::xalloc(); return rc; }
public:
astream(std::string const& name, std::ios_base::openmode mode)
: astream_base(name, mode)
, std::ios(&this->d_sbuf)
, std::iostream(&this->d_sbuf) {
this->iword(index()) = mode;
}
friend std::ios_base::openmode mode(std::iostream& stream) {
return std::ios_base::openmode(stream.iword(index()));
}
};
void print_mode(std::iostream& s) {
std::cout << "mode=" << mode(s) << "\n";
}
int main()
{
astream sin("test1", std::ios_base::in);
astream sout("test2", std::ios_base::out);
print_mode(sin);
print_mode(sout);
}
The astream_base is primarily needed to make sure the stream's stream buffer outlives the stream operations. In particular, the stream buffer needs to be alive when the std::ostream's destructor is called as that tries to call pubsync() to flush the stream buffer. Since std::ios is a virtual base of std::istream and std::ostream, the astream_base also needs to be a virtual base.
Other than that, the astream simply associates the used open mode with the std::iostream using an iword(). The function mode() can then be used to determine the value associated. If the stream wasn't open by an astream, the mode will be zero. If you want to support using other streams you could also allow setting the mode() flag which, however, becomes a bit less reliable.
you should set a variable for open mode. check this code:
fstream PatternFile;
ios_base::openmode currentOpenMode = ios_base::out;
strFile.Format(_T("yourFile.txt"));
PatternFile.open(strFile, currentOpenMode);
if(PatternFile.is_open())
{
if(currentOpenMode == ios_base::out)
{
// bingo
}
}
Related
I am trying to implement a file handle class similar to the one in Bjarne Stroustrup's FAQ page. (Scroll to "Why doesn't C++ provide a 'finally' construct".) Unlike his example, however, I want to use C++ file streams instead of a FILE*.
Right now, I am considering creating a FileHandleBase class, or something similarly named, and two derived classes—one for input files and one for output files. Below is the implementation I wrote as a proof-of-concept; keep in mind that it is very simple and unfinished.
class FileHandle {
public:
FileHandle(const char* fn, ios_base::openmode mode = ios_base::in | ios_base::out) {
file.open(fn, mode);
// Check to make sure file is open
}
FileHandle(const string &fn, ios_base::openmode mode = ios_base::in | ios_base::out) {
file.open(fn, mode);
// Check to make sure file is open
}
~FileHandle() {
file.close();
}
private:
fstream file;
};
I would like to know if this is a viable way of making a file handle, that is, whether my inheritance idea is good. I also want to know the best way to deal with the ios_base::openmode parameter because the C++ reference page for std::ifstream says this:
Note that even though ifstream is an input stream, its internal filebuf object may be set to also support output operations.
In what cases would an ifstream be used for output operations, and, similarly, when would an of stream be used for input operations; and should I restrict the options for the ios_base::openmode parameter for my file handle class(es)? That way my input file handle would only handle input operations, and the output version would only handle output operations.
In what cases would an ifstream be used for output operations, and, similarly, when would an ofstream be used for input operations
You would open an output file stream with an std::ios_base::in openmode and vice-versa for an input file stream if you would still like to perform those associated operations using the internal std::filebuf object, which is accessible by stream->rdbuf(). Note that the streams std::ofstream and std::ifstream will still be able to perform output and input respectively even if they are opened with opposite openmodes.
int main() {
std::ofstream stream("test.txt");
stream << "Hello" << std::flush;
stream.close();
stream.open("test.txt", std::ios_base::in);
char buffer[SIZE] = {};
stream.rdbuf()->sgetn(buffer, SIZE);
std::cout << buffer << std::endl;
}
I cannot figure out, is it possible to use std::basic_ifstream and std::basic_ofstream with a custom implementation of std::basic_filebuf?
How complicated can be an implementation of an input file stream that reads the file by blocks of 64KB size and internally checks some hash value of the block? If the hash is not valid it throws corruption_exception, for example. The output file stream writes the block and the hash value after it.
I found some examples that creates std::ifstream and then creates another stream that reads from it and does additional processing:
std::ifstream infile("test.img");
decompress_stream in(infile, 288);
char data[144 * 128];
in.read(data, 144 * 128);
infile.close();
But at first I expected it should be something like this (without an additional stream):
std::ifstrem in;
in.setbuffer(new MyBuffer());
in.read();
MyBuffer::underflow()
{
//read from original buffer
if (hash != calculated_sash) throw curruption_exception();
//return the data with omitted hash.
}
is this possible?
The file stream objects are effectively a combination of a std::basic_filebuf and a std::basic_[io]stream. The stream interface allows access to the std::basic_streambuf via the rdbuf() methods. Thus, you can replace the file stream stream buffer by another one. However, it wouldn’t have anything to do with the original file buffer.
As the stream buffer you have is a filtering stream buffer it may be reasonable to construct it with a stream and have the constructor inject the filter, i.e., something like this (I’m omitting the templates as these are irrelevant to this discussion but can easily be added):
class filterbuf
: public std::streambuf {
std::istream* istream = nullptr;
std::ostream* ostream = nullptr;
std::streambuf * sbuf;
// override virtual functions as needed
public:
explicit filterbuf(std::istream& in)
: istream(&in)
, sbuf(istream->rdbuf(this)) {
}
explict filterbuf(std::ostream& out)
: ostream(&out)
, sbuf(ostream->rdbuf(this)) {
}
explicit filebuf(std::iostream& inout)
: istream(&inout)
, sbuf(istream->rdbuf(this)) {
}
~filebuf() {
istream && istream->rdbuf(sbuf);
ostream && ostream->rdbuf(sbuf);
}
};
The point of restoring the stream buffer in the destructor is that the std::ostream destructor calls flush() on the object and the custom stream buffer is gone by that time.
The filter would be used like this:
std::istream fin(“whatever”);
filterbuf buf(fin);
if (fin >> whatever) {
...
}
If you want to customise the behaviour of iostreams the easiest way is to use boost::iostreams. Your use case could probably be implemented as an Inputfilter and an OutputFilter, you can use basic_file_source and basic_file_sink to read and write to files.
This question already has answers here:
Suppress output to cout from linked library
(6 answers)
Closed 7 years ago.
I'm using a 3rd party that sometimes has internal errors, when it happens the 3rd party writes to stderr and I can see it in the console.
(I do check the return values of the 3rd party functions and see that he's failed, but i want the information he writes to stderr)
I have a logger to whom I write using a method I have
SendLog(string log);
I want somehow to catch the things my 3rd party is writing to the stderr (maybe listen on the stderr some how) and then write this things to my log.
How can I do it ?
I need it because my users can't see the console, the only see the log.
It is important to note, my program doesn't crash or exists after those errors, it's continues to work.
EDIT:
My question is not the same as the allegedly similar question, I want to avoid using linker hacks (as been used in the similar question).
One solution is to duplicate everything that is written to cerr into for example a file.
This is the helper class:
class CTee {
public:
// Use ostream &s2 if you want to duplicate to an ostream, pass other
// stuff you need if you have other logging mechanisms.
CTee(ostream &s1, ostream &s2) : m_s1(s1), m_s1OrigBuf(s1.rdbuf()), m_teebuf(s1.rdbuf(), s2.rdbuf()) { s1.rdbuf(&m_teebuf); }
~CTee() { m_s1.rdbuf(m_s1OrigBuf); }
private:
CTee &operator =(CTee &rhs); // not implemented
class CTeeBuf : public streambuf {
public:
// Use streambuf *sb2 if you want to duplicate to an ostream/streambuf.
// Pass other Information if you want to log to something different.
CTeeBuf(streambuf* sb1, streambuf* sb2) : m_sb1(sb1), m_sb2(sb2) {}
protected:
virtual int_type overflow(int_type c) {
if(streambuf::traits_type::eq_int_type(c, streambuf::traits_type::eof()))
return c;
else {
// Put char to cerr/stream to duplicate
m_sb1->sputc((streambuf::char_type)c);
// Put char to duplicate stream. If you want to duplicate to something
// different, then write the char whereever you want to.
return m_sb2->sputc((streambuf::char_type)c);
}
}
virtual int sync() {
m_sb1->pubsync();
return m_sb2->pubsync();
}
// Store streambuf *m_sb2 if you want to duplicate to streambuf.
// Store anything else if you want to duplicate to something different.
streambuf *m_sb1, *m_sb2;
};
ostream &m_s1;
streambuf * const m_s1OrigBuf;
CTeeBuf m_teebuf;
};
CTee takes an ostream to duplicate and an ostream to duplicate to. It takes the ostream that shall be duplicated and replaces it's rdbuf, the streambuf that is written to, with a CTeeBuf (see CTee ctor). CTeeBuf takes the chars that are written to it and forwards them to the streambufs of both ostreams (see CTeeBuf::overflow and CTeeBuf::sync). The CTee dtor reverts the changed streambufs to their original values.
And it is used like this:
char logfilename[] = "myfile.log";
ofstream logfile(logfilename, ios_base::out | ios_base::app);
CTee tee(cerr, logfile);
From now on everything written to cerr will be duplicated to logfile (during the lifetime of tee). So this message will be written to cerr, but also to logfile:
cerr << "error occured: ..." << endl;
It is also possible to write to other ostreams than a logfile. If you don't want to duplicate to another ostream but to something else, just replace CTeeBuf::overflow by an implementation that logs whereever you want to.
See also http://www.cs.technion.ac.il/~imaman/programs/teestream.html and http://wordaligned.org/articles/cpp-streambufs.
One way is to use stringstream for this. If library write using c++streams that will work.
class redirect_stream
{
public:
redirect_stream(std::ostreamstream& stream, std::ostream& oldstream) :
stream_(stream), oldstream_(oldstream)
{
oldbuf_ = oldstream_.rdbuf();
oldstream_.rdbuf(stream_.rdbuf());
}
~redirect_stream()
{
const std::string str = stream_.str();
if (!str.empty())
{
SendLog(str);
}
oldstream_.rdbuf(oldbuf_);
}
private:
std::ostringstream& stream_;
std::ostream& olstream_;
std::streambuf* oldbuf_;
};
And before usage of 3rd party library just:
std::ostringstream oss;
redirect_stream redirecter(oss, std::cerr);
or you can not print message to log in destructor and just print oss.str() after the end of work with 3rd party library.
Simple usage example
You can use std::stringstream
std::stringstream log;
std::streambuf *buf = std::cerr.rdbuf(log).rdbuf());
std::cerr << "Error Msg" << std::endl;
std::string errMsg( log.str() );
errMsg will be "Error Msg".
I've created an fstream object to write info to files.
I write strings to the new file like
fStreamObject << "New message.\n";
because I want each << to print a string to the next line.
I want to be able to set a property and make a call like
fstreamObject << "New message.";
which will write the string to the next line.
Are there flags/settings for fstream objects that allows this to be done?
I've seen the different file modes (i.e. ofstream::in, ofstream::out, etc.), but I couldn't find one that auto writes to a new line. Also, I'm not looking to write my own solution. I want to be able to use a built in feature.
No, there are no readily configurable capabilities of that sort within the standard streams.
You may have to subclass the stream type and fiddle with operator<< to get this to work the way you want, or do it with a helper function of some description:
fstreamObject << nl("New message.");
(but that's hardly easier than just having the \n in there (for a string, anyway).
It depends on what you mean by "setting the stream". If we consider this to be fairly broad then the answer happens to be "yes"!
Here is how:
Create a stream buffer which inserts a newline every time it is flushed, i.e., when sync() is called. Otherwise it just forwards characters.
Change the file stream's stream buffer to use this stream buffer filtering to the file stream's stream buffer.
Set the flag std::ios_base::unitbuf which causes a flush after every [properly written] output operation.
Here are is the example code to do just that:
#include <iostream>
class newlinebuf
: public std::streambuf {
std::ostream* stream;
std::streambuf* sbuf;
int overflow(int c) { return this->sbuf->sputc(c); }
int sync() {
return (this->sbuf->sputc('\n') == std::char_traits::eof()
|| this->sbuf->pubsync() == -1)? -1: 0;
}
public:
newlinebuf(std::ostream& stream)
: stream(&stream)
, sbuf(stream.rdbuf(this)) {
stream << std::unitbuf;
}
~newlinebuf() { this->stream->rdbuf(this->sbuf); }
};
int main() {
newlinebuf sbuf(std::cout);
std::cout << "hello" << "world";
}
Although this approach work, I would recommend against using it! On problem is that all composite output operators, i.e., those using multiple output operators to do their work, will cause multiple newlines. I'm not aware of anything which can be done to prevent this behavior. There isn't anything in the standard library which enables just configuring the stream to do this: you'll need to insert the newline somehow.
No, the C++ streams do not allow that.
There is no way to decide where one insertion stops and the next starts.
For example for custom types, their stream-inserters are often implemented as calls to other stream-inserters and member-functions.
The only things you can do, is write your own class, which delegates to a stream of your choosing, and does that.
That's of strictly limited utiliy though.
struct alwaysenter {
std::ostream& o;
template<class X> alwaysenter& operator<<(X&& x) {
o<<std::forward<X>(x);
return *this;
}
};
In my application, I want to redirect the output that would normally go to the stdout stream to a function I define. I read that you can redirect stdio to a file, so why not to a function?
For example:
void MyHandler( const char* data );
//<<Magical redirection code>>
printf( "test" );
std::cout << "test" << std::endl;
//MyHandler should have been called with "test" twice, at this point
How can I achieve this / similar behaviour?
#Konrad Rudolph is right, you can totally do this, easily, at least for cout/cerr/clog. You don't even need your own streambuf implementation, just use an ostringstream.
// Redirect cout.
streambuf* oldCoutStreamBuf = cout.rdbuf();
ostringstream strCout;
cout.rdbuf( strCout.rdbuf() );
// This goes to the string stream.
cout << "Hello, World!" << endl;
// Restore old cout.
cout.rdbuf( oldCoutStreamBuf );
// Will output our Hello World! from above.
cout << strCout.str();
Same thing works for cerr and clog, but in my experience that will NOT work for stdout/stderr in general, so printf won't output there. cout goes to stdout, but redirecting cout will not redirect all stdout. At least, that was my experience.
If the amount of data is expected to be small, the freopen/setbuf thing works fine. I ended up doing the fancier dup/dup2 thing redirecting to a pipe.
Update: I wrote a blog post showing the dup2 method I ended up using, which you can read here. It's written for OS X, but might work in other Unix flavors. I seriously doubt it would work in Windows. Cocoa version of the same thing here.
Invoking a callback function whenever something’s written to the underlying standard output stream is hard: it requires overriding low-level, system-specific functions (on POSIX systems, it would require at least overriding write, and the way this is called might depend on the standard library implementation, so it might be different between e.g. glibc and musl).
But depending on what exactly you’re after you can solve this in C++ without resorting to low-level OS specific functions, by manipulating the C++ stream buffers directly.
For this you need to create your own std::streambuf implementation, i.e. your own stream buffer.
Once you have that, you can redirect the std::cout stream by switching the buffer:
auto buf = callback_streambuf(MyHandler);
auto pold_buffer = std::cout.rdbuf(&buf);
std::cout << "Hello" << std::cout;
// Restore original buffer:
std::cout.rdbuf(pold_buffer);
However, what this implementation won’t do is call your callback function exactly twice. Instead, the number of calls will depend on several factors, but it generally will not depend on the number of stream insertions (<<), and there is no way around that!
For the specific example above, the callback is called once, with the data "Hello\n".
The following minimal implementation illustrates how to get a streambuf to call your handler:
class callback_streambuf : public std::streambuf {
public:
callback_streambuf(std::function<void(char const*, std::streamsize)> callback) : callback(callback) {}
protected:
std::streamsize xsputn(char_type const* s, std::streamsize count) {
callback(s, count);
return count;
}
private:
std::function<void(char const*, std::streamsize)> callback;
};
This implementation has several caveats. For instance, it does the wrong thing when attempts are made to use it as an input stream. It doesn’t override overflow (since I don’t think this is ever called, although I find conflicting information about this on the internet; at any rate, adding overflow would be trivial). I didn’t implement synchronisation, so the callback will be called concurrently from multiple threads. Furthermore, there is no error handling, since the callback does not return a success status. I also had to change the signature of the callback to
void MyHandler(char const* data, std::streamsize count);
The second parameter is required since data isn’t a string, it’s a raw char buffer, so there is no way to determine its length intrinsically, and MyHandler can do nothing useful with the data without knowing its length.
Answer: Yes you can, via a dup. freopen will only reopen stdout to a file, as you talked about.
Check out How to buffer stdout in memory and write it from a dedicated thread
It's possible to disable stdin/stdout by dereferencing its pointer:
FILE fp_old = *stdout; // preserve the original stdout
*stdout = *fopen("/dev/null","w"); // redirect stdout to null
HObject m_ObjPOS = NewLibraryObject(); // call some library which prints unwanted stdout
*stdout=fp_old; // restore stdout
The std::cout object has a fixed meaning, and that is to output to the standard out stream. The user of your program gets to control where standard out is connected to, not you. What you can do is decide whether you wish to write to a file, to standard out or to any other output stream. So in your code you switch what stream you write to.
Again, the point of writing to the standard out stream is to give the user a flexibility in choosing where the output goes to. You're not supposed to redirect standard out; this is something the user is supposed to have the freedom to do.
Another thing is that you shouldn't mix C IO and C++ IO in a C++ program. Choose which IO library you wish to work with and stick to it.
That said, you can in C++ quite elegantly switch streams for a function to take input from by templating the handler function on the template parameters of std::basic_istream<>. Then the function will read its input from the input stream independently of the real kind of stream it's working with. Here's an example:
#include<iostream>
#include<fstream>
#include<string>
template<class Ch, class Tr>
void dodge_this(std::basic_istream<Ch, Tr>& in)
{
// in is an input stream. read from it as you read from std::cin.
}
int main(int argc, char* argv[])
{
if( std::string(argv[1]) == "cin" ) {
dodge_this(std::cin);
} else if( std::string(argv[1]) == "file" ) {
std::ifstream file("input.txt");
dodge_this(file);
} else {
dodge_this(dev_null_stream); // i just made that up. you get the idea.
}
}
Another option is to place your handler class calls into the inherited streambuf class. I had a requirement to redirect cout to a Win GUI edit control in a dialog box that may be of some use. Here is the class code:
//-------------------------------- DlgStringbuf Definition -----------------------
class DlgStringbuf : public std::stringbuf
{
public:
DlgStringbuf(void) : _hwndDlg(NULL), _editControlID(0), _accum(""), _lineNum(0) {}
void SetDlg(HWND dlg, int editControlID)
{ _hwndDlg = dlg; _editControlID = editControlID; }
void Clear(void)
{ _accum.clear(); _lineNum = 0; }
protected:
virtual std::streamsize xsputn(const char* s, std::streamsize num)
{
std::mutex m;
std::lock_guard<std::mutex> lg(m);
// Prepend with the line number
std::string str(s, (const uint32_t)num);
str = std::to_string(_lineNum) + ": " + str + "\r\n";
// Accumulate the latest text to the front
_accum = str + _accum;
// Write to the Win32 dialog edit control.
if(_hwndDlg != NULL)
SetDlgItemTextW(_hwndDlg, _editControlID, (LPCWSTR)(std::wstring(_accum.begin(), _accum.end())).c_str());
_lineNum++;
return(num);
}//end xsputn.
private:
std::string _accum;
HWND _hwndDlg;
int _editControlID;
uint32_t _lineNum;
};//end DlgStringbuf.
//-------------------------------- DlgStream Definition ------------------------------
class DlgStream : public std::ostream
{
public:
DlgStream(void) : std::ostream(&_sbuff) {}
void SetDlg(HWND dlg, int editControlID)
{ _sbuff.SetDlg(dlg, editControlID); }
void Clear(void)
{ _sbuff.Clear(); }
private:
DlgStringbuf _sbuff;
};
...and in the WinMain, someplace after the dialog box and its edit control is created:
// Redirect all cout usage to the activity dlg box.
// Save output buffer of the stream - use unique pointer with deleter that ensures to restore
// the original output buffer at the end of the program.
auto del = [&](streambuf* p) { cout.rdbuf(p); };
unique_ptr<streambuf, decltype(del)> origBuffer(cout.rdbuf(), del);
// Redirect the output to the dlg stream.
_dlgStream.SetDlg(hwndActivityDlg, IDC_EDIT_ACTIVITY);
_dlgStream.copyfmt(cout);
cout.rdbuf(_dlgStream.rdbuf());
cout << "this is from cout";
You can use sprintf to write to a character array and then read the value:
char buf[1024];
sprintf(buf, "test");
MyHandler(buf);
there are also snprintf and a few others depending on platform