C# 读取macOS .DS_Store文件 C#如何解析macOS的目录元数据文件

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

为什么 C# 直接读
.DS_Store
会失败或返回乱码

.DS_Store
是 macOS 用私有二进制格式(类似 AppleDouble + 自定义 B-tree)存的目录元数据,不是文本、不是 JSON、也不是标准 plist。C# 默认用
File.ReadAllText
StreamReader
去读,只会得到一堆无法解析的字节——甚至可能因编码误判直接抛
ArgumentException
(“Data at the root level is invalid” 这类错误其实和 XML 解析无关,只是字节流被强行当 UTF-8 解了)。

它不遵循任何公开文档化的序列化协议,Apple 也从未承诺格式稳定 macOS 12+ 开始部分字段加密或压缩,旧解析库大概率失效 结构含偏移表、节点块、属性键哈希,必须按字节布局逐段跳读,不能靠“找 key 名”硬匹配

DSStoreReader
库是最现实的选择

目前唯一持续维护、能处理较新 macOS 版本(包括 Ventura/Sonoma)的 .NET 库是开源的

DSStoreReader
(NuGet 包名:
DSStoreReader
)。它不依赖外部工具或 macOS 环境,纯 C# 实现,重点适配了 Apple 的实际字节布局变化。

安装:
dotnet add package DSStoreReader
基础读取:
var store = DSStoreReader.Read("/path/to/.DS_Store");
获取图标位置:
store.GetValue("ICVO", "Iloc")
→ 返回
PointF
,不是字符串
遍历所有键:
foreach (var entry in store.Entries)
,注意
entry.Key
是原始四字符码(如
"icvo"
),不是可读名

手动解析前必须绕开的三个坑

如果你真要自己写解析器(比如嵌入式场景不能引第三方),这些点踩中一个就卡死:

.DS_Store
文件头固定是
0x00 0x00 0x00 0x01
(big-endian int32),但 macOS 13 后某些情况会多出 16 字节签名头,得先跳过
内部 B-tree 节点的“key length”字段是变长编码(有时 1 字节,有时 2 字节),不能无脑
ReadByte()
字符串值(如文件夹备注)用的是 MacRoman 编码,不是 UTF-8;用
Encoding.GetEncoding(10000)
才能正确解码

Windows 上读 macOS 共享卷里的
.DS_Store
要额外注意路径

通过 SMB 挂载 macOS 共享(如

\mac-hostshare
)时,
.DS_Store
可能被 Windows 隐藏或拦截。常见现象是
File.Exists()
返回
false
,但实际文件存在。

确认 SMB 共享已启用 AppleDouble:macOS 端需设
afp.conf
或 SMB 配置中开启
fruit:metadata = stream
在 C# 中用 UNC 路径访问时,加
FileOptions.SequentialScan
可避免因隐藏属性导致的权限拒绝
若仍打不开,换用
Directory.GetFiles(path, ".DS_Store", SearchOption.AllDirectories)
,它比直接
File.OpenRead
更容错

事情说清了就结束。真正难的不是读出来,而是理解每个字段在不同 macOS 版本里代表什么——比如

"bwsp"
在 Catalina 是窗口大小,在 Monterey 里可能混进了缩略图尺寸,没对应系统版本测试,解析结果就是猜。

相关推荐