1. 程式人生 > >Boost Log : Wide character logging

Boost Log : Wide character logging

https 創建 works like nal 而不是 函數 pla art

Wide character logging

Log庫支持記錄包含不同national characters的字符串。基本上有兩種方法可以做到這一點。在類unix系統中,通常使用多字節字符編碼(例如UTF-8)來表示national characters。在這種情況下,Log庫可以像普通ASCII日誌記錄那樣使用,不需要任何額外設置。

在Windows上,常見的做法是使用寬字符串表示national characters。而且,大多數系統API都是面向寬字符的,這就要求特定於windows的sink也支持寬字符串。另一方面,通用sinks,比如文本文件sink,是面向字節的(因為,你將在文件中存儲字節,而不是字符)。這將強制Log庫在sink需要時執行字符代碼轉換。要為Log做這樣的設置,必須使用帶有適當codecvt方面的語言環境來設置sink。Boost.Locale可以用於生成這樣的語言環境。讓我們看一個例子:

// Declare attribute keywords
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)

void init_logging()
{
    boost::shared_ptr< sinks::synchronous_sink< sinks::text_file_backend > > sink = logging::add_file_log
    (
        "sample.log",
        keywords::format = expr::stream
            << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f")
            << " <" << severity.or_default(normal)
            << "> " << expr::message
    );

    // The sink will perform character code conversion as needed, according to the locale set with imbue()
    std::locale loc = boost::locale::generator()("en_US.UTF-8");
    sink->imbue(loc);

    // Let's add some commonly used attributes, like timestamp and record counter.
    logging::add_common_attributes();
}

首先,讓我們看一下傳入format參數的formatter。我們使用窄字符formatter初始化sink,因為文本文件sink處理字節。可以在formatter中使用寬字符串,但不能在格式字符串中使用,就像我們在format_date_time函數中使用的一樣。還要註意,我們使用message關鍵字來表示log record消息。這個占位符支持窄字符和寬字符消息,所以formatter可以同時使用這兩種消息。作為格式化過程的一部分,Log庫將使用輸入的語言環境(我們將其設置為UTF-8)將寬字符消息轉換為多字節編碼。

Tip
Attribute values也可以包含寬字符串。Log record消息一樣,這些字符串將使用設置的語言環境轉換為目標字符編碼。

這裏缺少的一點是我們的severity_level類型定義。該類型只是一個枚舉,但如果我們想要支持其窄格式和寬字符格式的sink,其stream操作符必須是模板。如果我們使用不同的字符類型創建多個sinks,這可能會很有用。

enum severity_level
{
    normal,
    notification,
    warning,
    error,
    critical
};

template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (
    std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
{
    static const char* const str[] =
    {
        "normal",
        "notification",
        "warning",
        "error",
        "critical"
    };
    if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str)))
        strm << str[lvl];
    else
        strm << static_cast< int >(lvl);
    return strm;
}

現在我們可以發出log records。我們可以使用帶有w前綴的loggers來組成寬字符消息。

void test_narrow_char_logging()
{
    // Narrow character logging still works
    src::logger lg;
    BOOST_LOG(lg) << "Hello, World! This is a narrow character message.";
}

void test_wide_char_logging()
{
    src::wlogger lg;
    BOOST_LOG(lg) << L"Hello, World! This is a wide character message.";

    // National characters are also supported
    const wchar_t national_chars[] = { 0x041f, 0x0440, 0x0438, 0x0432, 0x0435, 0x0442, L',', L' ', 0x043c, 0x0438, 0x0440, L'!', 0 };
    BOOST_LOG(lg) << national_chars;

    // Now, let's try logging with severity
    src::wseverity_logger< severity_level > slg;
    BOOST_LOG_SEV(slg, normal) << L"A normal severity message, will not pass to the file";
    BOOST_LOG_SEV(slg, warning) << L"A warning severity message, will pass to the file";
    BOOST_LOG_SEV(slg, error) << L"An error severity message, will pass to the file";
}

如您所見,寬字符消息組合類似於窄日誌記錄。註意,您可以同時使用窄字符和寬字符日誌;所有記錄將由我們的文件sink處理。這個示例的完整代碼可以在這裏找到。

必須註意的是,有些sinks(大部分是特定於windows的)允許指定目標字符類型。當日誌記錄中需要使用national characters時,應該始終使用wchar_t作為目標字符類型,因為sink將使用寬字符OS API來處理log records。在這種情況下,當執行格式化時,所有窄字符字符串都將使用嵌入到sink中的locale進行加寬。

Boost Log : Wide character logging