Using C++ Filestreams (Fstream), How to Determine the Size of a File

Using C++ filestreams (fstream), how can you determine the size of a file?

You can open the file using the ios::ate flag (and ios::binary flag), so the tellg() function will directly give you directly the file size:

ifstream file( "example.txt", ios::binary | ios::ate);
return file.tellg();

How can I determine the current size of the file opened by std::ofstream?

fstreams can be both input and output streams. tellg() will return the input position and tellp() will tell you of the output position. tellp() will after appending to a file tell you its size.

Consider initializing your Logger like this (edit: added example for output stream operator):

#include <iostream>
#include <fstream>

class Logger {
std::string m_filename;
std::ofstream m_os;
std::ofstream::pos_type m_curr_size;
std::ofstream::pos_type m_max_size;
public:
Logger(const std::string& logfile, std::ofstream::pos_type max_size) :
m_filename(logfile),
m_os(m_filename, std::ios::app),
m_curr_size(m_os.tellp()),
m_max_size(max_size)
{}

template<typename T>
friend Logger& operator<<(Logger&, const T&);
};

template<typename T>
Logger& operator<<(Logger& log, const T& msg) {
log.m_curr_size = (log.m_os << msg << std::flush).tellp();

if(log.m_curr_size>log.m_max_size) {
log.m_os.close();
//rename & compress
log.m_os = std::ofstream(log.m_filename, std::ios::app);
log.m_curr_size = log.m_os.tellp();
}
return log;
}

int main()
{
Logger test("log", 4LL*1024*1024*1024*1024);
test << "hello " << 10 << "\n";
return 0;
}

If you use C++17 or have an experimental version of <filesystem> available, you could also use that to get the absolute file size, like this:

#include <iostream>
#include <fstream>
#include <filesystem>

namespace fs = std::filesystem;

class Logger {
fs::directory_entry m_logfile;
std::ofstream m_os;
std::uintmax_t m_max_size;

void rotate_if_needed() {
if(max_size_reached()) {
m_os.close();
//rename & compress
m_os = std::ofstream(m_logfile.path(), std::ios::app);
}
}
public:
Logger(const std::string& logfile, std::uintmax_t max_size) :
m_logfile(logfile),
m_os(m_logfile.path(), std::ios::app),
m_max_size(max_size)
{
// make sure the path is absolute in case the process
// have changed current directory when we need to rotate the log
if(m_logfile.path().is_relative())
m_logfile = fs::directory_entry(fs::absolute(m_logfile.path()));
}

std::uintmax_t size() const { return m_logfile.file_size(); }
bool max_size_reached() const { return size()>m_max_size; }

template<typename T>
friend Logger& operator<<(Logger&, const T&);
};

template<typename T>
Logger& operator<<(Logger& log, const T& msg) {
log.m_os << msg << std::flush;
log.rotate_if_needed();
return log;
}

int main()
{
Logger test("log", 4LL*1024*1024*1024*1024);
std::cout << test.size() << "\n";
test << "hello " << 10 << "\n";
std::cout << test.size() << "\n";
test << "some more " << 3.14159 << "\n";
std::cout << test.size() << "\n";
return 0;
}

How can I get a file's size in C++?


#include <fstream>

std::ifstream::pos_type filesize(const char* filename)
{
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
return in.tellg();
}

See http://www.cplusplus.com/doc/tutorial/files/ for more information on files in C++.

edit: this answer is not correct since tellg() does not necessarily return the right value. See http://stackoverflow.com/a/22986486/1835769

How does a program determine the size of a file without reading it whole?

The size of the file is embedded in the file metadata in the file system. Different file systems have different ways of storing this information.

Edit Obviously, this is an incomplete answer. When someone will provide an answer where he'll exemplify on a common filesystem like ex3 or ntfs or fat exactly how the file size it's known and stored, i'll delete this answer.

Get file size with std::ios::ate?

It should work just fine. The C++ standard says about std::ios::ate

ate - open and seek to end immediately after opening

There's no reason it would fail when a manual open-then-seek would succeed. And tellg is the same in either case.

filestream to vector, filesize wrong

std::istream_iterator<unsigned char> is a formatted input iterator that skips whitespace, that is why your vector is short.

Use std::istreambuf_iterator<char> instead, it reads data verbatim.

Note that the meaning of the template argument is quite different between these two iterators. In the latter case it is the type of symbols decoded by std::char_traits<> (e.g. you may want to decode a utf-8 encoded file as sequence of wchar_t). std::istreambuf_iterator<char> does identity decoding. C++ streams have been using char type for representing binary data (see std::ostream::write, for example).



Related Topics



Leave a reply



Submit