浅谈log4cpp接口字符串参数类型的设计

log4cpp是个开源项目的C++日志库,该库的license是LGPL, 我们的项目里使用了它。它的接口字符串参数类型全是std::string,只支持窄字符字符串。以前的同事更改了log4pp库的部分源码,使接口字符串参数可以处理std::wstring(宽字符字符串),我们的项目里使用到的字符串恰好都是std::wstring类型的。
 
出于对开源价值的认同,我认为:
? log4cpp和log4j系出同门,而Java默认的字符串就是宽字符组成的,因此log4cpp应该也有机制提供
? 对于一个被广泛使用的开源项目,不可能没有考虑过这个问题
 
google上搜索了一把,没有任何关于log4cpp如何日志宽字符字符串的信息,那么只好自己动手了,有代码还怕啥? tea in, code out!
代码里搜索了一下std::wstring以及wchar_t,发现了整个库只有CategoryStream流的opeartor<<函数的参数是std::wstring字符串, 找了篇log4cpp的介绍文章”便利的开发工具-log4cpp快速使用指南”(http://www.ibm.com/developerworks/cn/linux/l-log4cpp/index.html), 又仔细hack了下log4cpp代码,终于尝试出来如何日志宽字符字符串的代码。
请看:
 

//unicode style
   static void DoLog(Category& logger, Priority::Value priority, const wchar_t* stringFormat, …)
   {
        CategoryStream  &stream = logger.getStream(priority);
 
        wchar_t pBuf[5000] = {0};
        va_list args;
        va_start(args, stringFormat);
        vswprintf_s(pBuf, sizeof(pBuf) / sizeof(pBuf[0]), stringFormat, args);
 
        std::wstring msg(pBuf);
 
       stream.operator<<<std::wstring>(msg);
   }

最后一行十分变态: stream.operator<<<std::wstring>(msg);
stream类的operator<<是一个模板,并且有一个“半模板实例化的”std::wstring参数类型的operator<<,
但是可惜原型是写成这样的:
template<typename T>
   CategoryStream& operator<<(const std::wstring& t) {
          if (getPriority() != Priority::NOTSET) {
              if (!_wbuffer) {
                  if (!(_wbuffer = new std::wostringstream)) {
                      // XXX help help help
                  }
              }
              (*_wbuffer) << t;
          }
          return *this;
      }

 
这里模板参数typename T是没有用到的,所以才有了上面那么变态的代码。
打开日志文件后发现,输入到日志文件里的的确是宽字符。如果日志”xuminggang”,则显示成”x u m i n g g a n g”, 稀松宽拉, 很不正常!查看16进制,每个字符都变成了在英文字母对应的窄字符后面添加了0.反思一下,我们平时看到的文件是宽字符的吗?没有!
是的,没有!
    
回头来看,log4cpp库的接口字符串类型设计成std::string是正确的,任何一个日志库最终日志到文件中去的都是窄字符格式(或宽字符编码后的格式,譬如utf-8), 因为你平时使用编辑器打开的常见文本文件都是这种格式。你可能会说utf-8这种unicode编码格式的文件也很常见啊!是的,通过std::wstring转换成utf-8格式的字符,最后的数据类型还是std::string的!因此如果要日志宽字符字符串,则可以先转换成窄字符字符串,然后再日志!
    
再退一步看了看以前同事修改的代码,跟踪调试了一下,发现虽然更改了接口字符串参数类型为宽字符类型,但是内部日志的地方还是进行了一层 转换,将宽字符转换成窄字符,只不过添加了许多复杂的功能(譬如通过读文件头的BOM来判断是否是utf-8或utf-16编码格式日志文件等等)。
 对于我们的项目,我想完全可以在LGPL的约束下使用log4cpp。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值