2013-12-19 189 views
1

我的应用程序当前登录的一个非常简单的方法:限制文件流的文件大小?

void Log::create(const std::string& path, bool append) 
{ 
    if(append) 
    m_log.open(path.c_str(),std::ios_base::out | std::ios_base::app); 
    else 
     m_log.open(path.c_str(),std::ios_base::out | std::ios_base::trunc); 
} 

std::ofstream& Log::get() 
{ 
    return m_log; 
} 

void Log::write(const std::string& what) 
{ 
    get() << "[" << TimeOfDay::getDate() << "] "; 
    get() << what << std::endl; 
} 

void Log::write(const std::string& where, const std::string& what) 
{ 
    get() << "[" << TimeOfDay::getDate() << "] "; 
    get() << "[" << where << "] " << what << std::endl; 
} 

std::ofstream& Log::write() 
{ 
    get() << "[" << TimeOfDay::getDate() << "] "; 
    return get(); 
} 

std::ofstream Log::m_log; 

此应用程序的服务器上运行。现在,如果日志超过了某个文件大小,我想停止日志记录。

有没有办法做到这一点,没有提升或其他图书馆?

感谢

+1

难道你不能通过在各种'write()'重载中递增计数器来记录写入的行数吗? Boost.Filesystem具有['file_size'](http://www.boost.org/libs/filesystem/doc/reference.html#file_size)函数,可以实现您想要的功能。 MSVC 2013附带一个基于Boost的''实现,因此如果您使用该编译器,它应该提供相同的功能。 – Praetorian

回答

3

您可以创建设置写入文件,但停止,如果它写比数据的指定金额写一个过滤流缓冲区。事情是这样的:

class limitbuf 
    : public std::streambuf { 
    std::streambuf* sbuf; 
    size_t   size; 
    size_t   limit; 
    char   buffer[1024]; 
public: 
    limitbuf(std::streambuf* sbuf, size_t limit) 
     : sbuf(sbuf), limit(limit), size(0) 
    { 
     this->setp(buffer, buffer + 1023); 
    } 
    int overflow(int c) { 
     if (c != std::char_traits<char>::eof()) { 
      this->pptr() = std::char_traits<char>::to_char_type(c); 
      this->pbump(1); 
     } 
     return this->sync() == 0 
      ? std::char_traits<char>::not_eof(c) 
      : std::char_traits<char>::eof(); 
    } 
    int sync() { 
     if (this->size < limit) { 
      this->size += this->sbuf->sputn(this->pbase(), 
       std::min(
        size_t(this->pptr() - this->pbase()), 
        this->limit - this->size) 
       ); 
      this->sbuf->pubsync(); 
     } 
     this->setp(this->pbase(), this->epptr()); 
     return 0; 
    } 
}; 

该流缓冲区作为过滤器只需安装到你的日志文件,它应该被限制到一些合适的尺寸:

std::ofstream out("some.log", 16384); 
limitbuf  sbuf(out.rdbuf()); 
std::ostream log(&sbuf); 

此流缓冲区的基本思想是相当简单:数据是缓冲器内部并且在缓冲区溢出或在冲洗写:

  • 当建立与setp()缓冲器溢出流与调用overflow(c)下一个要写入的字符(或可能与std::char_traits<char>::eof())。由于te流缓冲区被告知比实际可用的小一个字符的缓冲区,溢出字符将被添加到缓冲区,并且整个缓冲区被刷新。
  • 当缓冲区被刷新时(例如在std::ostream上使用std::endl写入此缓冲区),函数sync()最终被调用。它只是编写当前缓冲的字符。代码只是看看是否还有空间写入任何内容,并在有可用空间时写入该字符。 size成员会维护写入了多少个字符,并设置limit以指示要写入多少数据。

如果流缓冲区不仅仅限制输出,可能需要修改发生的逻辑,如果没有更多的空间。例如,如果存在无法写入的剩余字符,则流缓冲区可能会决定打开一个新文件(并可能移动其他文件)。

+0

我还需要能够移动日志,如果它已满,然后将在其位置创建一个新的日志。 – jmasterx

+0

@Milo:你之前没有提到过这个要求......无论如何:这项技术大致相同。您可能会在用于日志记录的流缓冲区中保留一个“std :: filebuf”,并将基名称作为配置。在'sync()'中,您不会停止写入,而是关闭现有文件,重命名现有的日志,可能达到极限,然后打开一个新文件并写入该文件。 –

+0

@jrok:呃,是...(更正) –