用 System.IO
直接读 ISO 文件?不行,会报错
ISO 9660 是文件系统格式,不是普通压缩包。直接对
.iso文件调用
Directory.GetFiles或
new DirectoryInfo()会抛出
IOException:“找不到文件的一部分”,因为 .NET 基础 I/O 不理解 ISO 9660 的目录结构和 LBA 映射逻辑。
常见错误现象:把 ISO 当成 ZIP 用
ZipArchive打开 → 报
InvalidDataException;或用
FileStream+
StreamReader乱读 → 得到一堆不可读字节。 ISO 不是归档格式(如 ZIP/RAR),它是一块“虚拟磁盘”的原始镜像,含引导区、卷描述符、路径表、目录记录等
System.IO只支持 FAT/NTFS/exFAT 等挂载后的卷,不解析光盘文件系统元数据 Windows 虽能双击挂载 ISO,但那是 shell 和
cdrom.sys在背后做的,.NET 层无感知
推荐方案:用 DiscUtils
库解析 ISO 9660
DiscUtils是目前最稳定、文档最清晰的纯 C# ISO 9660 解析库(MIT 开源,NuGet 包名:
DiscUtils.Iso9660)。它不依赖 Windows API 或外部工具,所有解析都在托管代码中完成。
使用场景:离线读取 ISO 内容、提取特定文件、遍历目录树、获取文件时间戳或隐藏属性。
安装命令:dotnet add package DiscUtils.Iso9660核心类是
Iso9660FileSystem,构造时传入
Stream(必须可 seek,不能是
NetworkStream) 注意:ISO 文件必须完整且未损坏,部分刻录中途失败的镜像可能缺少主卷描述符,
Iso9660FileSystem会直接 throw
InvalidDataException示例代码片段:
using DiscUtils.Iso9660;
using var isoStream = File.OpenRead("game.iso");
using var fs = new Iso9660FileSystem(isoStream);
foreach (var file in fs.GetFiles("/")) {
Console.WriteLine(file); // 输出类似 "/README.TXT"
}路径写法和大小写敏感性容易踩坑
ISO 9660 Level 1 规范强制文件名 8.3 格式、全大写、无 Unicode。虽然 Level 2/3 和 Joliet 扩展支持长名和小写,但
DiscUtils默认按 Joliet 优先(如果存在),否则回落到 Rock Ridge 或标准 ISO。
这意味着你看到的路径可能是
/Documents/Report.pdf(Joliet),也可能是
/DOCUMENTS/REPORT.PDF(Level 1),甚至带 Rock Ridge 扩展的
/documents/report.pdf(小写+长名)——取决于原始镜像如何生成。 不要硬编码路径大小写,用
fs.GetDirectories(path)和
fs.GetFiles(path)枚举后匹配,而不是直接
fs.OpenFile("/DATA/FILE.TXT")
路径分隔符始终用正斜杠 /,即使在 Windows 上;反斜杠
\会导致
ArgumentException根路径必须写成
"/",不是
""或
"./",否则
GetFiles返回空
性能与内存:大 ISO 镜像别一次性加载
DiscUtils.Iso9660FileSystem构造时会解析整个 ISO 的目录结构(PVD、path table、directory records),但不会把所有文件内容读进内存。不过,如果 ISO 超过 4GB,且你的进程是 x86,可能因地址空间不足而触发
OutOfMemoryException(尤其在 32 位调试模式下)。 确保项目目标平台设为
x64(右键项目 → 属性 → 生成 → 平台目标) 避免反复 new
Iso9660FileSystem—— 它内部缓存了关键元数据,复用实例更高效 如果只查某几个文件,不用遍历全盘,直接用
fs.GetFileEntry("/path/to/file") 拿元数据,再按需 OpenFile流式读取 流必须保持打开状态直到
Iso9660FileSystem释放,否则后续操作会 throw
ObjectDisposedException
ISO 文件系统解析本身不慢,但首次构造
Iso9660FileSystem对超大镜像(如 DVD-9)仍可能耗几百毫秒,这部分延迟没法绕开——毕竟得从开头找到卷描述符,再跳转到目录区位置。
