如何确定由std :: ofstream打开的文件的当前大小? [英] How can I determine the current size of the file opened by std::ofstream?

查看:991
本文介绍了如何确定由std :: ofstream打开的文件的当前大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类,其文件流的类型为ofstream.构造函数以追加模式打开文件,并且所有消息总是写在文件末尾.

I have a class that has a filestream of type ofstream. The constructor opens the file in append mode and all the messages always get written at the end of the file.

我需要以最大固定大小(例如1Mb)写入outputFile,然后我需要关闭,重命名和压缩它,然后打开一个同名的新文件.

I need to write into outputFile up to some fixed size say 1Mb, then I need to close, rename, and compress it, and then open a new file of the same name.

当达到一定大小的文件时,需要执行此操作.

This needs to be done when a certain size of file is reached.

我尝试使用tellg(),但是在阅读了相关内容(和)在互联网上,我知道这不是正确的方法.

I tried using tellg() but after reading stuffs (and this) on internet, I understood that this is not the right approach.

由于我是C ++的新手,所以我试图找到最优化,最正确的方法来获取由ofstream打开的文件的当前当前大小?

As I'm new to C++, I'm trying to find out the most optimized and correct way to get the accurate current size of file opened by ofstream?

class Logger {
    std::ofstream outputFile;
    int curr_size;
    Logger (const std::string logfile) : outputFile(FILENAME,
                                                     std::ios::app)
    {
        curr_size = 0;
    }
};

在程序的某个地方,我正在向其中写入数据

Somewhere in the program, I'm writing data into it:

    // ??? Determine the size of current file ???

    if (curr_size >= MAX_FILE_SIZE) {
        outputFile.close();
        //Code to rename and compress file
        // ...
        outputFile.open(FILENAME, std::ios::app);
        curr_size = 0;
    }

    outputFile << message << std::endl;
    outputFile.flush();

推荐答案

fstreams既可以是输入流,也可以是输出流. tellg()将返回输入位置,而tellp()将告诉您输出位置. tellp()将在附加到文件后告诉您文件的大小.

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.

考虑像这样初始化您的Logger(为输出流运算符添加了示例):

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;
}

如果您使用C ++ 17或具有<filesystem>的实验版本,则还可以使用它来获取绝对文件大小,如下所示:

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;
}

这篇关于如何确定由std :: ofstream打开的文件的当前大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆