0

Usecase: I am trying to write a logging function which writes to a .gz (compressed) file or a non-compressed file based on user input.

My code:

typedef boost::iostreams::filtering_streambuf<boost::iostreams::output> boost_output_buffer;
.
.
.

fstream *tmp_file;
if(_compressed){
    tmp_file = new ofstream(file_path, ios_base::out | ios_base::binary | ios_base::app);
} else {
    tmp_file = new ofstream(file_path, ios_base::out | ios_base::app);
}
boost_output_buffer *outbuf = new boost_output_buffer();
if(_compressed){
    outbuf->push(*(new boost::iostreams::gzip_compressor()));
}
outbuf->push((*tmp_file));
_fileStreamPtr = new ostream(outbuf);
.
.
.
(*_fileStreamPtr) << "Hello World\n";

Note that I am using pointers everywhere because I have already tried without them, and honestly I wasn't sure where I was going wrong so I tried using pointers. (In my use case I want these pointers and opened files till the end of my code, so deallocation doesn't matter)

For _compressed = false, this code creates a file at "file_path", but doesn't output any text to it.

Please help.

EDIT
As mentioned in the comments, I tried producing a minimum example.
Even on using this, the "Hello World" gets printed only once the program exits. How can I ensure this get printed at "<<" line itself?
(I am not sure but I think closing the file has a significant overhead. If that is true, then I don't want that since I am doing this operation a large number of times in my project)

#include <fstream>
#include <iostream>
#include <string>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include "unistd.h"

using namespace std;
typedef boost::iostreams::filtering_streambuf<boost::iostreams::output> boost_output_buffer;

int main(int argc, char* argv[]){

    ofstream tmp_file(argv[1], ios_base::out | ios_base::app);

    boost_output_buffer outbuf;
    outbuf.push(tmp_file);

    ostream mystream(&outbuf);

    (mystream) << "Hello World\n";

    sleep(15);

    return 0;
}
  • Note that I am also trying to use zlib in another place and its also failing. `int ret_val = gzwrite(_file, data.c_str(), sizeof(char)*data.size());` This returns a positive value (which is the correct number of bytes), but nothing is being written in the actual file – ztart14578 Aug 25 '23 at 09:28
  • What you should do is simplify. Start with a three line program, open the file, write to it. Does any output appear in the file? If yes, then the problem is some difference between your three line program and the complete program, investigate that. If no then at least you have a smaller program to work with. One you could post here in it's entirety maybe. – john Aug 25 '23 at 09:36
  • Note that if you do use pointers then you will need to close the file to see any output. Without pointers the file will close when the objects are destroyed, without pointers this will not happen (because with pointers and no delete nothing is ever destroyed). – john Aug 25 '23 at 09:41
  • @john thanks for the response. Can you please suggest some other way around this? (I have added an edit) – ztart14578 Aug 25 '23 at 10:02
  • 1
    In your second example the stream wont be line buffered unlike `std::cout` so you'll need an explicit `flush()` – Alan Birtles Aug 25 '23 at 10:04
  • @AlanBirtles Thanks! I had to add `my_stream.flush(); tmp_file.flush();` to make it work. But does it have a significant time overhead? If yes, then whats the best way to achieve this? – ztart14578 Aug 25 '23 at 10:43
  • @ztart14578 Flushing will add time overhead, that's the nature of flushing. Obviously the time itself varies by platform, and how significant that is for you is something only you can tell. The simplest to achieve a flush though (in your example code) is `mystream << "Hello World" << std::endl;`. `std::endl` outputs a newline and then causes the stream to be flushed, which seems to be what you want. – john Aug 25 '23 at 12:16
  • @john got it. Thanks for the help! – ztart14578 Aug 25 '23 at 17:11

0 Answers0