2013-12-19 228 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:呃,是...(更正) –