Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: get number of characters printed when using ofstream

Tags:

c++

io

c++03

The C fprintf() function returns the number of characters printed. Is there similar functionality in C++ when writing to a file with ofstream? I am interested in a solution that is compatible with C++03 if possible.

For example:

ofstream file("outputFile");
file << "hello";

// Here would I like to know that five characters were printed.

file << " world";

// Here I would like to know that six characters were printed.
like image 762
user327301 Avatar asked Dec 17 '14 21:12

user327301


2 Answers

What you're looking for is tellp().

You could use it like so:

ofstream file("outputFile");

auto pos1 = file.tellp();
file << "hello";
auto pos2 = file.tellp();
std::cout << pos2 - pos1 << std::endl;
like image 161
Borgleader Avatar answered Nov 18 '22 13:11

Borgleader


Seek operations are rather expensive (primarily because they need to prepare streams to potentially switch between reading and writing). I'd personally rather use a filtering stream buffer which provides the counts, e.g.:

class countbuf: public std::streambuf {
    std::streambuf* sbuf;
    std::size_t     count;
    char            buffer[256];
    int overflow(int c) {
        if (c != std::char_traits<char>::eof()) {
            *this->pptr() = c;
            this->pbump(1);
        }
        return this->sync() == -1
            ? std::char_traits<char>::eof()
            : std::char_traits<char>::not_eof(c);
    }
    int sync() {
        std::size_t size(this->pptr() - this->pbase());
        this->count += size;
        this->setp(this->buffer, this->buffer + 256);
        return size == this->sbuf->sputn(this->pbase(), this->pptr() - this->pbase())
             ? this->sbuf->pubsync(): -1;
    }
public:
    countbuf(std::streambuf* sbuf): sbuf(sbuf), count() {
        this->setp(buffer, buffer + 256);
    }
    std::size_t count() const { return count + this->pptr() - this->pbase(); }
    std::size_t reset() const {
        std::size_t rc(this->count());
        this->sync();
        this->count = 0;
        return rc;
    }
};

Once you got this stream buffer, you could just install into an std::ostream (and possibly package the construction into a custom stream class):

countbuf     sbuf(std::cout.rdbuf()); // can't seek on this stream anyway...
std::ostream out(&sbuf);
out << "hello!\n" << std::flush;
std::cout << "count=" << out.reset() << '\n';
like image 39
Dietmar Kühl Avatar answered Nov 18 '22 14:11

Dietmar Kühl