【问题标题】:NSLog() vs printf() when printing C string (UTF-8)打印 C 字符串 (UTF-8) 时的 NSLog() 与 printf()
【发布时间】:2014-05-15 07:36:53
【问题描述】:

我注意到,如果我尝试使用格式说明符“%s”打印包含 UTF-8 字符串表示的字节数组,printf() 会正确,但NSLog() 会出现乱码(即,每个字节都按原样打印,例如“¥”被打印为 2 个字符:“¬•”)。 这很好奇,因为我一直以为NSLog()就是printf(),加上:

  1. 第一个参数(“格式”)是 Objective-C 字符串,而不是 C 字符串(因此是“@”)。
  2. 前置的时间戳和应用程序名称。
  3. 在末尾自动添加换行符。
  4. 能够打印 Objective-C 对象(使用格式“%@”)。

我的代码:

NSString* string; 

// (...fill string with unicode string...)

const char* stringBytes = [string cStringUsingEncoding:NSUTF8Encoding];

NSUInteger stringByteLength = [string lengthOfBytesUsingEncoding:NSUTF8Encoding];
stringByteLength += 1; // add room for '\0' terminator

char* buffer = calloc(sizeof(char), stringByteLength);

memcpy(buffer, stringBytes, stringByteLength);

NSLog(@"Buffer after copy: %s", buffer);
// (renders ascii, no matter what)

printf("Buffer after copy: %s\n", buffer);
// (renders correctly, e.g. japanese text)

不知何故,看起来printf()NSLog() 更“聪明”。有谁知道根本原因,以及是否在任何地方记录了此功能? (没找到)

【问题讨论】:

  • 当然,实际的解决方案是将NSLog UTF8 字符串作为NSStringnot 作为C 字符串。但在这种特殊情况下,我想检查 char 缓冲区是否被正确复制。

标签: ios objective-c utf-8 printf nslog


【解决方案1】:

NSLog()stringWithFormat: 似乎期待 %s 的字符串 在“系统编码”中(例如我电脑上的“Mac Roman”):

NSString *string = @"¥";
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(CFStringGetSystemEncoding());
const char* stringBytes = [string cStringUsingEncoding:enc];
NSString *log = [NSString stringWithFormat:@"%s", stringBytes];
NSLog(@"%@", log);

// Output: ¥

当然,如果某些字符在系统编码中无法表示,这将失败。我找不到有关此行为的官方文档,但可以看到在 stringWithFormat:NSLog() 中使用 %s 不能可靠地处理任意 UTF-8 字符串。

如果要检查包含 UTF-8 字符串的 char 缓冲区的内容,则 这适用于任意字符(使用装箱表达式语法从 UTF-8 字符串创建 NSString):

NSLog(@"%@", @(utf8Buffer));

【讨论】:

  • 哦,巧妙的技巧...我不知道那种语法。有点像@(1)、@[a、b、c]、@{@"key":value} 等。
  • 顺便说一句,我在 iOS 设备上进行测试;还没在 Mac 上试过。
猜你喜欢
  • 2013-03-09
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
  • 2011-01-08
  • 2023-03-27
  • 2019-11-07
  • 2011-07-09
  • 1970-01-01
相关资源
最近更新 更多