开源HYBUnicodeReadable日志显示Unicode中文

原文出自:标哥的技术博客

前言

开发中经常需要打印日志以查看数据是否正确,或者说查看数据的格式。但是,苹果对于我们的NSDictionaryNSSetNSArray等值有中文时,打印出来的是Unicode编码,人类无法直接读懂,因此,笔者研究研究如何将打印出来的日志保持原有的格式化且能够将Unicode编码打印出来是正常人类可读懂的中文。

实现原理

苹果给我们提供了本地化的方法,对于NSDictionaryNSSetNSArray都可以重写该方法来实现:

NSSet实现

对于NSSet实现如下:

- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {
  NSMutableString *desc = [NSMutableString string];

  NSMutableString *tabString = [[NSMutableString alloc] initWithCapacity:level];
  for (NSUInteger i = 0; i < level; ++i) {
    [tabString appendString:@"\t"];
  }

  NSString *tab = @"\t";
  if (level > 0) {
    tab = tabString;
  }
  [desc appendString:@"\t{(\n"];

  for (id obj in self) {
    if ([obj isKindOfClass:[NSDictionary class]]
        || [obj isKindOfClass:[NSArray class]]
        || [obj isKindOfClass:[NSSet class]]) {
      NSString *str = [((NSDictionary *)obj) descriptionWithLocale:locale indent:level + 1];
      [desc appendFormat:@"%@\t%@,\n", tab, str];
    } else if ([obj isKindOfClass:[NSString class]]) {
      [desc appendFormat:@"%@\t\"%@\",\n", tab, obj];
    } else {
      [desc appendFormat:@"%@\t%@,\n", tab, obj];
    }
  }

  [desc appendFormat:@"%@)}", tab];

  return desc;
}

我们这里根本缩进级别来生成对应的格式化字符串,以便解决多级嵌套时格式不太美观的问题。

NSArray实现

对于NSArray的实现如下:

- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {
  NSMutableString *desc = [NSMutableString string];

  NSMutableString *tabString = [[NSMutableString alloc] initWithCapacity:level];
  for (NSUInteger i = 0; i < level; ++i) {
    [tabString appendString:@"\t"];
  }

  NSString *tab = @"";
  if (level > 0) {
    tab = tabString;
  }
  [desc appendString:@"\t(\n"];

  for (id obj in self) {
    if ([obj isKindOfClass:[NSDictionary class]]
        || [obj isKindOfClass:[NSArray class]]
        || [obj isKindOfClass:[NSSet class]]) {
      NSString *str = [((NSDictionary *)obj) descriptionWithLocale:locale indent:level + 1];
      [desc appendFormat:@"%@\t%@,\n", tab, str];
    } else if ([obj isKindOfClass:[NSString class]]) {
      [desc appendFormat:@"%@\t\"%@\",\n", tab, obj];
    } else {
      [desc appendFormat:@"%@\t%@,\n", tab, obj];
    }
  }

  [desc appendFormat:@"%@)", tab];

  return desc;
}

同样的道理,不过笔者对于字符串值,都加上了双引号,一眼就可以看出来是字符串类型。

NSDictionary实现

对于NSDictonary的实现如下:

- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {
  NSMutableString *desc = [NSMutableString string];

  NSMutableString *tabString = [[NSMutableString alloc] initWithCapacity:level];
  for (NSUInteger i = 0; i < level; ++i) {
    [tabString appendString:@"\t"];
  }

  NSString *tab = @"";
  if (level > 0) {
    tab = tabString;
  }

  [desc appendString:@"\t{\n"];

  // 遍历数组,self就是当前的数组
  for (id key in self.allKeys) {
    id obj = [self objectForKey:key];

    if ([obj isKindOfClass:[NSString class]]) {
      [desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, obj];
    } else if ([obj isKindOfClass:[NSArray class]]
               || [obj isKindOfClass:[NSDictionary class]]
               || [obj isKindOfClass:[NSSet class]]) {
      [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, [obj descriptionWithLocale:locale indent:level + 1]];
    } else {
      [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];
    }
  }

  [desc appendFormat:@"%@}", tab];

  return desc;
}

字典打印出来的格式是{}这样的结构,我们一样要考虑嵌套情况,并且根据嵌套添加对应的级别缩进。

升级版本到Version1.0

新增NSData类型自动打印出可视化内容,只要是新增类似这样的处理:

else if ([obj isKindOfClass:[NSData class]]) {
  // 如果是NSData类型,尝试去解析结果,以打印出可阅读的数据
  NSError *error = nil;
  NSObject *result =  [NSJSONSerialization JSONObjectWithData:obj
                                                      options:NSJSONReadingMutableContainers
                                                        error:&error];
  // 解析成功
  if (error == nil && result != nil) {
    if ([result isKindOfClass:[NSDictionary class]]
        || [result isKindOfClass:[NSArray class]]
        || [result isKindOfClass:[NSSet class]]) {
      NSString *str = [((NSDictionary *)result) descriptionWithLocale:locale indent:level + 1];
      [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, str];
    } else if ([obj isKindOfClass:[NSString class]]) {
      [desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, result];
    }
  } else {
    @try {
      NSString *str = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];
      if (str != nil) {
        [desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, str];
      } else {
        [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];
      }
    }
    @catch (NSException *exception) {
      [desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];
    }
  }
}

我们只是尝试去解析可视化数据,若解析成功则显示出来,若解析失败就原样输出。

测试

我们来测试一下效果,我们打印如下一个字典:

NSString *str = @"我是转换成data格式的字符串";
NSData *dataString = [NSData dataWithBytes:str.UTF8String length:str.length];
NSDictionary *dataSet = @{@"key": @"字典转成data",
                          @"key1": @"在set、数组、字典中嵌套"};
NSData *dataSetItem = [NSJSONSerialization dataWithJSONObject:dataSet
                                                      options:NSJSONWritingPrettyPrinted
                                                        error:nil];

NSMutableSet *set = [NSMutableSet setWithArray:@[@"可变集合",
                                                 @"字典->不可变集合->可变集合",
                                                 dataSetItem]];
NSDictionary *dict = @{@"name"  : @"标哥的技术博客",
                       @"title" : @"http://www.henishuo.com",
                       @"count" : @(11),
                       @"dataString" : dataString,
                       @"results" : [NSSet setWithObjects:@"集合值1", @"集合值2", set , nil],
                       @"summaries" : @[@"sm1",
                                        @"sm2",
                                        @{@"keysm": @{@"stkey": @"字典->数组->字典->字典"}},
                                        dataSetItem],
                       @"parameters" : @{@"key1" : @"value1",
                                         @"key2": @{@"key11" : @"value11",
                                                    @"key12" : @[@"三层", @"字典->字典->数组"]},
                                         @"key13": dataSetItem},
                       @"hasBug": @[@"YES",@"NO"],
                       @"contact" : @[@"关注博客地址:http://www.henishuo.com",
                                      @"QQ群: 324400294",
                                      @"关注微博:标哥Jacky",
                                      @"关注GITHUB:CoderJackyHuang"]};
NSLog(@"%@", dict);

打印效果如下:

2015-12-31 16:47:42.352 demo[58176:2693559]     {
    hasBug =    (
        "YES",
        "NO",
    ),
    dataString = "我是转换成",
    title = "http://www.henishuo.com",
    count = 11,
    results =   {(
        "集合值2",
        "集合值1",
            {(
            "可变集合",
            "字典->不可变集合->可变集合",
                {
                key = "字典转成data",
                key1 = "在set、数组、字典中嵌套",
            },
        )},
    )},
    summaries =     (
        "sm1",
        "sm2",
            {
            keysm =     {
                stkey = "字典->数组->字典->字典",
            },
        },
            {
            key = "字典转成data",
            key1 = "在set、数组、字典中嵌套",
        },
    ),
    contact =   (
        "关注博客地址:http://www.henishuo.com",
        "QQ群: 324400294",
        "关注微博:标哥Jacky",
        "关注GITHUB:CoderJackyHuang",
    ),
    name = "标哥的技术博客",
    parameters =    {
        key1 = "value1",
        key13 =     {
            key = "字典转成data",
            key1 = "在set、数组、字典中嵌套",
        },
        key2 =  {
            key11 = "value11",
            key12 =     (
                "三层",
                "字典->字典->数组",
            ),
        },
    },
}

如何使用

首先要得到源代码,安装方式有两种,一种是直接使用Cocoapods

pod 'HYBUnicodeReadable', '~> 1.0'

或者直接下载源代码https://github.com/CoderJackyHuang/HYBUnicodeReadable,放入工程中即可

温馨提示:不需要引入头文件,即可达到效果!

写在最后

如果在使用过程中出现任何bug,请反馈作者以便及时修正!谢谢您的支持!

如果觉得赞,请给一个star

关注我

如果在使用过程中遇到问题,或者想要与我交流,可加入有问必答QQ群:324400294

关注微信公众号:iOSDevShares

关注新浪微博账号:标哥Jacky

支持并捐助

如果您觉得文章对您很有帮助,希望得到您的支持。您的捐肋将会给予我最大的鼓励,感谢您的支持!

支付宝捐助 微信捐助
时间: 2024-08-02 18:52:13

开源HYBUnicodeReadable日志显示Unicode中文的相关文章

sqlite3 qt-QT 显示sqlite中文乱码问题

问题描述 QT 显示sqlite中文乱码问题 数据库是在sqlite3里通过insert语句形成的,网上说这样子字符串是utf_8编码,而中文是gb2312编码,在QT显示时字符串正常,而中文是乱码.在QT里试了很多编码转换方式都不行啊!请解.. 解决方案 把gb编码转换成unicode.再转成utf8

OGre(1.65)+CEGUI的中文显示和中文输入,新人必看

第一次学博客,好刺激.刚学Ogre一个星期,遇到了一些难点,但经过网海的打捞终于慢慢的前行.今天遇到的中文显示和输入的问题!中文显示还好弄的,但中文输入我历经九九八十一个网页,却终究没能解决,正值吃饭之际,也不知是怎么打开的一个充满神奇的网页,里面居然又源代码,而且还是1.60版本的Ogre(我用的1.65,虽然出了1.70但是我的机子运行出了点问题.反正初学能用就好了).内容十分相近,下载一下,稍稍阅读,震惊不已.Application的cpp里面就两行就"解决"了!感慨万分之余,怕

PHP开源Apache日志分析工具收集与比较

我们知道已经有很多像Awtstat这样的使用perl.c或者c++开发的强大的日志分析工具,但是同样也有很多使用PHP开发并且开源的日志分析软件,今天我就收集了一些与大家分享. 1.LogAnalyzer LogAnalyzer是 Adiscon的监控软件产品线中的一部分.可以再Windows以及Unix环境下运行.LogAnalyzer本是是免费的,GPL许可的产品. LogAnalyzer的原名为phpLogCon,他在2010年的3月29日发布了3.0的稳定版,并且正式改名为LogAnal

unknown source-android 异常发生的位置日志显示类名.a(unknow source) 是什么意思?

问题描述 android 异常发生的位置日志显示类名.a(unknow source) 是什么意思? E/RRCTRL_RADIO( 1276): RadioSSeeking>>>freq=96400signal=0.E/AndroidRuntime( 1796): FATAL EXCEPTION: mainE/AndroidRuntime( 1796): java.lang.IndexOutOfBoundsException: Invalid index 10 size is 10E/

cmd显示utf8中文

cmd无法显示utf8的中文.于是找搜索引擎问了一下.得到了一个有个很屌丝的命令chcp. 如果要显示utf8中文. 可以按照如下操作 1. 执行如下命令 chcp 65001 2.修改cmd属性.字体为"Lucida Console"

jdbc-数据在数据库中查询显示是中文,输出到页面转换为utf-8之后,输出为乱码,求解

问题描述 数据在数据库中查询显示是中文,输出到页面转换为utf-8之后,输出为乱码,求解 <%@page import="java.sql.ResultSet"%> <%@page import="java.sql.Statement"%> <%@page import="java.sql.DriverManager"%> <%@page import="java.sql.Connection&

nginx日志不支持中文

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://navyaijm.blog.51cto.com/4647068/1082169 今天遇到一个奇怪的问题,nginx的access日志不支持中文,其中我的环境变量是支持中文的: 最后的解决办法把nginx的版本降低(原先是1.2.1现在是1.0.5) 未将版本前的日志: 119.14.15.78 - - [06/Dec/2012:20:40:58 +0800] "GET /wide

reportviewer上按钮文字无法显示成中文

问题描述 请教各位高手,小弟做了个网页使用了reportviewer在自己机器上测试时reportviewer上面的按钮如"上一页"."下一页"."导出"等按钮都显示为中文,为什么把网页装上服务器上时这些文字都显示为英文的了?难道和服务器的设置有关?请教请教 解决方案 解决方案二:对的解决方案三:那到底什么地方没设置好呢?解决方案四:我也遇到这个问题求解解决方案五:再别的地方找到这么一个答案打包的时候加上Microsoft.ReportViewe

PropertyGrid中的枚举显示为中文(转)

本文转载:http://www.cnblogs.com/yank/archive/2011/09/17/2179598.html   ropertyGrid中的枚举显示为中文 在系统开发中,经常会使用PropertyGrid来修改或者展示某个对象的属性,如果类中定义了枚举,在展现的时候默认会展示枚举的项或者枚举值,但是这并不是我们想要的.用户使用的时候并不清楚该项代表的意思.之前介绍过枚举显示中文的一篇文章,大家可以看下,枚举显示中文. 想要的效果: 在PropertyGrid中枚举显示中,又比