如何确定std::ofstream打开的文件的当前大小?
How can I determine the current size of the file opened by std::ofstream?
我有一个 class,它有一个 ofstream
类型的文件流。构造函数以追加模式打开文件,所有消息始终写入文件末尾。
我需要写入 outputFile 到某个固定大小,比如 1Mb,然后我需要关闭、重命名和压缩它,然后打开一个同名的新文件。
当文件达到一定大小时需要执行此操作。
我尝试使用 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();
我用 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
fstreams 可以是输入流和输出流。 tellg()
将 return 输入位置,而 tellp()
将告诉您输出位置。 tellp()
将在附加到文件后告诉您它的大小。
考虑像这样初始化您的记录器(编辑:为输出流运算符添加示例):
#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;
}
我有一个 class,它有一个 ofstream
类型的文件流。构造函数以追加模式打开文件,所有消息始终写入文件末尾。
我需要写入 outputFile 到某个固定大小,比如 1Mb,然后我需要关闭、重命名和压缩它,然后打开一个同名的新文件。
当文件达到一定大小时需要执行此操作。
我尝试使用 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();
我用 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
fstreams 可以是输入流和输出流。 tellg()
将 return 输入位置,而 tellp()
将告诉您输出位置。 tellp()
将在附加到文件后告诉您它的大小。
考虑像这样初始化您的记录器(编辑:为输出流运算符添加示例):
#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;
}