plist文件不是json,需用apple的corefoundation(macos/ios)或跨平台libplist解析;强行用json/xml库会失败,因plist含特有标签和类型映射规则。

PLIST文件不是JSON,别直接用jsoncpp或nlohmann/json硬解
PLIST是Apple定义的序列化格式,有XML和二进制两种编码。C++标准库不原生支持,强行当XML或JSON解析会失败——比如遇到<date></date>、<data></data>、<true></true>这类标签时,通用XML解析器可能忽略语义,JSON库则直接报错Unexpected token 。
真正能正确还原类型(如NSDate → std::chrono::system_clock::time_point、CFData → std::vectorlibplist。
macOS上优先用CoreFoundation API:轻量、零依赖、类型精准
如果你只面向macOS,CFPropertyListCreateFromXMLData是最稳妥的选择。它自动识别XML/二进制PLIST,并返回CFPropertyListRef,再用CFDictionaryGetValue、CFArrayGetValueAtIndex等安全取值。
使用ydata-profiling(前身为pandas-profiling)生成全面的数据质量报告,包含相关性分析、缺失值模式和基数检测。导出交互式HTML仪表板和JSON摘要。
- 必须用
CFRelease释放返回的CFPropertyListRef,否则内存泄漏 -
CFString转std::string要用CFStringGetCString+kCFStringEncodingUTF8,不能直接强转指针 -
CFDateRef需用CFDateGetAbsoluteTime转为CFAbsoluteTime(自2001-01-01起的秒数),再换算成std::time_t或std::chrono::seconds - 示例关键片段:
CFDataRef plistData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8*)xmlBytes, len, kCFAllocatorNull); CFPropertyListRef plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, plistData, kCFPropertyListImmutable, &error); // ... 使用后调用 CFRelease(plist); CFRelease(plistData);
跨平台项目必须用libplist:但注意它的C接口和内存模型
libplist(https://github.com/libimobiledevice/libplist)是iOS/macOS逆向工具链中广泛使用的开源实现,支持Linux/Windows/macOS,但它是纯C接口,且所有节点对象(plist_t)需手动管理生命周期。
- 解析失败时
plist_from_xml返回NULL,但不会告诉你哪一行出错——建议先用plutil -lint xxx.plist验证文件有效性 - 读取字符串必须用
plist_get_string_val,不能直接访问plist->value字段(结构体未公开) - 二进制PLIST需用
plist_from_bin,XML用plist_from_xml,混用会导致segfault - 释放整个树用
plist_free,不要逐层free子节点
别自己手写解析器:PLIST的边缘case太多
看似简单的XML PLIST,实际包含大量非标准扩展:<key></key>必须紧跟<string></string>或<integer></integer>,<dict></dict>内键名隐式有序,<data></data>是base64编码且可能含空字节,<date></date>格式固定为ISO8601但带时区(如2023-05-12T14:30:00Z)。这些规则在libplist和CoreFoundation里都已处理,自己实现极易漏掉<real></real>的科学计数法解析或<array></array>嵌套深度限制。
真正需要定制的,只是从解析后的CFDictionaryRef或plist_t映射到你的C++ struct——这部分用一层薄封装就够了,没必要碰底层语法分析。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










