C# 读取Apple PList文件 C#如何解析macOS和iOS使用的XML或二进制属性列表

来源:这里教程网 时间:2026-02-21 17:43:01 作者:

PlistCS
读取 XML 和二进制 PList 最省事

直接上结论:C# 没有原生 PList 支持,

PlistCS
是目前最轻量、兼容性最好、能同时处理 XML 和二进制格式的开源库。它不依赖 macOS 或 .NET Core 特定运行时,.NET Framework 4.6+ 和 .NET 5/6/7/8 都能跑。

常见错误是硬啃 Apple 官方文档自己解析二进制格式——

NSKeyedArchiver
生成的不是标准 PList,而
CFBinaryPlist
格式又没公开完整规范,极易在字节对齐、浮点编码、日期偏移上翻车。

安装:
dotnet add package PlistCS
(NuGet)
它自动识别文件头:
bplist00
→ 二进制;
<?xml 
/code> → XML
不支持
NSKeyedArchiver
序列化产物(那种带
$class
$classes
的),那是另一套序列化机制,不是 PList

PlistParser.Parse
怎么用才不崩

别直接传路径字符串进去——

PlistParser.Parse
接收的是
Stream
byte[]
,传错类型会抛
NullReferenceException
或静默返回空字典。

典型场景:读取 macOS 的

Info.plist
或 iOS 导出的
Manifest.plist
。这些文件可能带 BOM、换行不一致,但
PlistParser.Parse
内部已处理,你只需确保流可读且未被释放。

正确写法:
var dict = PlistParser.Parse(File.OpenRead("Info.plist"));
错误写法:
PlistParser.Parse("Info.plist")
(编译不过)或
PlistParser.Parse(File.ReadAllText(...))
(类型不匹配)
返回值是
IDictionary<string object></string>
,嵌套结构里
object
可能是
string
DateTime
long
bool
IDictionary<string object></string>
IList<object></object>
,需运行时判断

遇到
Invalid binary plist header
错误怎么办

这通常不是文件损坏,而是你把非 PList 文件当 PList 读了——比如误读了

embedded.mobileprovision
(那是 PKCS#7 签名数据)或
AppIcon20x20@2x.png
(图片),它们开头也可能是乱码,但根本不是 PList。

更隐蔽的情况:某些工具导出的“PList”其实是 JSON 伪装的(比如部分配置管理平台),或者用了 UTF-16 编码但没写 BOM,XML 解析器会卡在第一个字符。

先用命令行确认:
file Info.plist
(macOS/Linux)或看十六进制头:
bplist00
(二进制)、
3C 3F 78 6D 6C
(<?xml )
如果头是
6A 73 6F 6E
(json),别用
PlistParser
,换
System.Text.Json
二进制 PList 若含自定义类型(如
CFTypeRef
子类),
PlistCS
会跳过并记录警告,不会崩溃,但对应 key 的 value 为
null

IDictionary<string object></string>
安全取值的坑

很多人写

dict["CFBundleIdentifier"].ToString()
就跑,结果遇到 key 不存在、值为
null
、或值其实是
NSNumber
映射的
long
却强转
string
,直接
NullReferenceException
或格式错乱。

特别是

CFBundleVersion
可能是整数(iOS 早期)或字符串(现代),
UIBackgroundModes
是数组,
NSLocationWhenInUseUsageDescription
是字符串——类型不统一是常态。

安全取字符串:
dict.TryGetValue("CFBundleIdentifier", out var idObj) && idObj is string id ? id : null
取整数版本号:
dict.TryGetValue("CFBundleVersion", out var vObj) && int.TryParse(vObj?.ToString(), out var ver) ? ver : 0
取数组并遍历:
if (dict.TryGetValue("UIBackgroundModes", out var modesObj) && modesObj is IList<object> modes)</object>

二进制 PList 里的日期会被自动转成

DateTime
(UTC),但 XML PList 里是 ISO 8601 字符串,
PlistCS
统一做了转换,这点不用额外处理——但如果你手动改过源码或用了旧版,就得自己 parse。

相关推荐

热文推荐