我有一个类,其文件流类型为ofstream
。构造函数以附加模式打开文件,并且所有消息总是写在文件末尾。
我需要以最大固定大小(例如1Mb)写入outputFile,然后关闭,重命名和压缩它,然后打开一个同名的新文件。
当达到一定大小的文件时,需要执行此操作。
我尝试使用tellg()
,但在互联网上阅读了东西(和this)后,我知道这是不正确的方法。
由于我是C ++的新手,所以我试图找出最优化,最正确的方法来获取ofstream
打开的文件的当前准确大小?
class Logger {
std::ofstream outputFile;
int curr_size;
Logger (const std::string logfile) : outputFile(FILENAME,
std::ios::app)
{
curr_size = 0;
}
};
在程序的某个地方,我正在向其中写入数据:
// ??? 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();
答案 0 :(得分:2)
fstreams既可以是输入流,也可以是输出流。 tellg()
将返回输入位置,而tellp()
将告诉您输出位置。 tellp()
将在附加到文件后告诉您文件的大小。
考虑像这样初始化您的Logger(编辑:添加了输出流运算符的示例):
#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>
的实验版本,也可以使用它来获取绝对文件大小,如下所示:
#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;
}
答案 1 :(得分:1)
我尝试了tellp()
,对我来说效果很好:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream myFile("data.txt", ios_base::app);
myFile << "Hello World!" << endl;
cout << myFile.tellp() << endl;
return 0;
}
这是调用此程序时的输出:
$ ./program
13
$ ./program
26
$ ./program
39
答案 2 :(得分:1)
使用std::ofstream::tellp()
std::ofstream file{"file.txt", std::ios::app};
std::cout << "file size: " << file.tellp();