使用C#的ZipArchive创建zip压缩包时是否可以保留原目录结构?
这个需求完全可以实现,你当前的写法没有保留目录结构的原因是ZipArchive.CreateEntryFromFile方法的第二个参数指定的是文件在压缩包内的完整路径,你目前只传入了item.Name(仅文件名),因此所有文件都会被直接存放在压缩包的根目录,不会携带原有目录结构。
方案1:保留文件相对于指定公共根目录的路径(最常用)
这种场景适合你打包的所有文件都归属同一个上层公共目录,最终压缩包内只会保留该根目录以下的层级结构,不会暴露完整的绝对路径,修改后的代码如下:
public static void CreateZipFile(IEnumerable<FileInfo> files, string archiveName, string rootDirectory) { // 统一处理根目录路径,确保末尾带路径分隔符,避免前缀截取错误 var processedRoot = Path.GetFullPath(rootDirectory).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; using (var stream = File.OpenWrite(archiveName)) using (var archive = new ZipArchive(stream, ZipArchiveMode.Create)) { foreach (var item in files) { // 计算文件相对于根目录的路径,作为压缩包内的条目路径 var entryPath = item.FullName.Substring(processedRoot.Length); archive.CreateEntryFromFile(item.FullName, entryPath, CompressionLevel.Optimal); } } }
调用示例:如果你所有待打包文件都在D:\Project\Resource目录下,调用时传入该路径作为第三个参数即可,压缩包内会自动保留Resource目录下的子目录层级。
方案2:保留文件的完整绝对路径
如果你需要在压缩包内保留文件的完整绝对路径(比如C:\Docs\Note\a.txt会完整存到压缩包内),直接修改第二个参数为item.FullName即可:
public static void CreateZipFile(IEnumerable<FileInfo> files, string archiveName) { using (var stream = File.OpenWrite(archiveName)) using (var archive = new ZipArchive(stream, ZipArchiveMode.Create)) { foreach (var item in files) { archive.CreateEntryFromFile(item.FullName, item.FullName, CompressionLevel.Optimal); } } }
补充说明
- 如果你传入的文件来自多个完全不相关的根目录,没有公共父级,建议你自定义每个文件在压缩包内的映射路径,避免目录混乱。
- 路径分隔符在Zip规范中兼容正斜杠和反斜杠,无需额外转换,Windows和其他系统解压都能正常识别目录结构。
内容的提问来源于stack exchange,提问作者ErocM
相关产品推荐
相关产品推荐

