boost.log(八)宽字符记录

宽字符记录

Boost.Log支持包含本地字符集字符串的日志记录。基本上有两种方式做这件事。在 UNIX 系统上通常使用一些多字节字符编码 (例如 UTF-8) 用来表示本地字符。在这种情况下,Boost.Log库可以直接以纯 ASCII 的方式记录而不需要其它额外的设置。

在Windows 上常见的做法是使用宽字符串来表示本地字符串。此外大多数系统 API 也是使用的宽字符,这需要特定于 Windows 的接收器也支持宽字符。另一方面,通用的接收器,例如 TextFile,是面向字节的,你写入文件的是字节,而不是字符。这迫使Boost.Log库进行字符编码转换时需要通过接收器。在接收器上指定合适的区域设置,Boost.Locale 可以用于生成这种区域设置。让我们看看一个例子:

  1. // Declare attribute keywords
  2. BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
  3. BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
  4. void init_logging()
  5. {
  6. boost::shared_ptr< sinks::synchronous_sink< sinks::text_file_backend > > sink = logging::add_file_log
  7. national characters (
  8. "sample.log",
  9. keywords::format = expr::stream
  10. << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f")
  11. << " <" << severity.or_default(normal)
  12. << "> " << expr::message
  13. );
  14. // The sink will perform character code conversion as needed, according to the locale set with imbue()
  15. std::locale loc = boost::locale::generator()("en_US.UTF-8");
  16. sink->imbue(loc);
  17. // Let‘s add some commonly used attributes, like timestamp and record counter.
  18. logging::add_common_attributes();
  19. }

首先让我们看看传入格式化器中的格式参数,我们初始化一个非宽字符格式化器的接收器,因为文本文件接收处理的是字节。可以在格式化器中使用宽字符串,但不是在格式字符串,就像我们使用的format_date_time函数("%Y-%m-%d, %H:%M:%S.%f"不能是宽字符)。另外请注意,我们使用的 message 关键字来表示日志记录信息。此占位符支持非宽字符和宽字符的信息,所以格式化器将使用两者。作为格式的过程的一部分,Boost.Log库将转换为宽字符消息使用了多字节的区域编码,我们设置为UTF-8。

[提示]属性值也可以包含宽字符串。像日志记录的消息,这些字符串将被转换以imbued locale为目标的字符编码。

在这里我们缺少severity_level类型定义。类型仅仅是一个枚举,但如果我们想要其格式支持宽和非宽字符的接收器,就需要对它流的<<运算符重载模板函数进行特化了。

  1. enum severity_level
  2. {
  3. normal,
  4. notification,
  5. warning,
  6. error,
  7. critical
  8. };
  9. template< typename CharT, typename TraitsT >
  10. inline std::basic_ostream< CharT, TraitsT >& operator<< (
  11. std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
  12. {
  13. static const char* const str[] =
  14. {
  15. "normal",
  16. "notification",
  17. "warning",
  18. "error",
  19. "critical"
  20. };
  21. if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str)))
  22. strm << str[lvl];
  23. else
  24. strm << static_cast< int >(lvl);
  25. return strm;
  26. }

现在我们可以发出消息了,但是必须要用 "w" 为前缀的记录器来撰写消息记录。

  1. void test_narrow_char_logging()
  2. {
  3. // Narrow character logging still works
  4. src::logger lg;
  5. BOOST_LOG(lg) << "Hello, World! This is a narrow character message.";
  6. }
  7. void test_wide_char_logging()
  8. {
  9. src::wlogger lg;
  10. BOOST_LOG(lg) << L"Hello, World! This is a wide character message.";
  11. // National characters are also supported
  12. const wchar_t national_chars[] = { 0x041f, 0x0440, 0x0438, 0x0432, 0x0435, 0x0442, L‘,‘, L‘ ‘, 0x043c, 0x0438, 0x0440, L‘!‘, 0 };
  13. BOOST_LOG(lg) << national_chars;
  14. // Now, let‘s try logging with severity
  15. src::wseverity_logger< severity_level > slg;
  16. BOOST_LOG_SEV(slg, normal) << L"A normal severity message, will not pass to the file";
  17. BOOST_LOG_SEV(slg, warning) << L"A warning severity message, will pass to the file";
  18. BOOST_LOG_SEV(slg, error) << L"An error severity message, will pass to the file";
  19. }

正如你所看到的,宽字符消息组成类似于非宽字符消息。请注意,您可以在同一时间同时使用宽和非字符记录,所有记录都将通过我们文件接收器进行处理。这个例子的完整代码可以在这里找到。

必须指出的是一些接收器(主要是Windows特定的)允许指定目标的字符类型。如果期望使用本地字符写日志记录,应始终使用 wchar_t 作为目标字符类型。因为接收器将采用宽字符的操作系统API来处理日志记录。

时间: 2024-08-02 22:28:03

boost.log(八)宽字符记录的相关文章

boost.log要点笔记

常用简写: namespace logging = boost::log; namespace src = boost::log::sources; namespace expr = boost::log::expressions; namespace sinks = boost::log::sinks; namespace attrs = boost::log::attributes; namespace keywords = boost::log::keywords; 要点: 结构图要牢记在

boost.log(九) 配置文件

前面几节中描述了Boost.Log 的基础知识,对Boost.Log 库的操作我们都是在C++代码中进行中,这样就会有一些不便的地方.比如说我们想要更改一下输出格式或者过滤条件,都必须对C++代码进行更改,并且还得编译一次(感觉编译时间还有点长).其实Boost.Log 里面已经为这个问题提供了一种解决方案,就是通过配置文件来初始化Boost.Log 库,C++这边的代码也比较简单,就是这样的: std::ifstream settings("settings.txt"); if (!

boost.log(六)格式化

如果你尝试运行上一节中的例子,你会发现只有日志记录消息(没有时间戳等属性信息)会被写入到文件.这是因为boost.log库没有设置格式化.即使你添加了属性到boost.log的core或者是记录器中,记录值也不会被输出,除非你指定了这些值的格式. 回到在前面节教程的一个例子: #include <iostream> #include <boost/log/utility/setup/file.hpp> #include <boost/log/sinks/basic_sink_

宽字符,Ansic和Unicode

电脑发展的初期,只是在美国等英文国家使用,英文只有26个字母和其它字符,一个字节最多可以表示256个字符,如字母“A”用0x41(二进制01000001)表示,字母“a”用0x61(二进制01100001)表示.为了使各家电脑公司生产的电脑统一,美国搞了个国家标准ANSI,一直沿用至今,我们今天用的电脑普通情况下使用的都ANSI编码. ANSI编码,每个字符占一个字节,但最多只能表示256个字符.汉字等东亚语言字符怎么办呢?于是采用两个字节共同表示一个汉字的方法.二个字节理论上可以表示65535

Boost Log 基本用法

Boost Log 基本用法 flyfish 2014-11-5 根据boost提供的代码示例,学习Boost Log 的基本用法 前提 boost版本boost_1_56_0 示例代码文件夹 boost_1_56_0\libs\log\example\basic_usage 使用的单词很形象,整个过程就像流水一样 假设要输出的日志比作水 水                     (Hello, World!) 水槽                 (sink) 流向哪里        (co

Android NDK 下的宽字符编码转换及icu库的使用(转)

原贴http://topic.csdn.net/u/20101022/16/1b2e0cec-b9d2-42ea-8d9c-4f1bb8320a54.html?r=70149216 ,看过并动手实现,记录下来以备再用. 如果是在java层,有String类可以很好的转换各种编码,在ndk下面就没有现成的公开的工具,不过可以用icu4c. ICU4C 是IBM的国际化开发组件ICU的C语言实现版本.在android系统里也有实现.ndk里面并没有公开可用的api,需要自己加载动态库来调用转换函数.

通过编写串口助手工具学习MFC过程&mdash;&mdash;(三)Unicode字符集的宽字符和多字节字符转换

通过编写串口助手工具学习MFC过程 因为以前也做过几次MFC的编程,每次都是项目完成时,MFC基本操作清楚了,但是过好长时间不再接触MFC的项目,再次做MFC的项目时,又要从头开始熟悉.这次通过做一个串口助手再次熟悉一下MFC,并做了一下记录,以便方便以后查阅.做的过程中多是遇到问题直接百度和谷歌搜索来的,所以很多都是不求甚解,知其然不知其所以然.另外做此工具只是为了熟悉了解,许多功能还没有完善!(开发工具VS2008) (三)Unicode字符集的宽字符和多字节字符转换 在上一节<(二)通过&qu

宽字节(宽字符)注入

字节注入也是在最近的项目中发现的问题,大家都知道%df' 被PHP转义(开启GPC.用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\',其中\的十六进制是 %5C ,那么现在 %df\' =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MYSQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗',也就是说:%df\' = %df%5c%27=縗',有了单引号就好注入了.比如: $conn = mysql_connect("lo

ACE服务端编程2:ACE跨平台之数据类型和宽字符

ACE网络库的主要优势之一就是跨平台,ACE提供了操作系统API和编译器级别的跨平台解决方法,使开发人员不用再去关心操作系统和编译器的差异,但因此也带来了ACE的复杂性. ACE网络库的组织结构主要分为四层:OS适配层.wrapper facade层.框架层.服务层,其中OS适配层为操作系统API提供了包装函数,保证了系统级的跨平台特性. 而不同的C++编译器在以下方面也有明显的差异: 1.模版: 2.数据类型和宽字符: 3.运行时初始化和关闭: 4.分配堆内存: 以上主要参考自APG里内容,但