如何使用ZipArchive类删除WAR包内指定路径的特定文件
解决方案
问题根因
原删除函数仅匹配了ZipArchiveEntry的Name属性(仅存储纯文件名,不带包内路径),因此传入完整路径时无法匹配命中,且重名文件会被全部删除。Zip包内文件的完整路径存储在FullName属性中,且Zip规范默认路径不带开头的/,需要先对传入路径做格式化处理再匹配。
1. 改进后的Remove-FilesFromZip函数(支持按路径删除)
function Remove-FilesFromZip { param( [string]$ZipFile, [string]$FileName ) $zip = $null $stream = $null try { [Reflection.Assembly]::LoadWithPartialName('System.IO.Compression') | Out-Null $stream = New-Object IO.FileStream($ZipFile, [IO.FileMode]::Open) $mode = [IO.Compression.ZipArchiveMode]::Update $zip = New-Object IO.Compression.ZipArchive($stream, $mode) # 格式化传入路径,适配Zip内部路径规范 $cleanPath = $FileName.TrimStart('/','\').Replace('\','/') # 优先匹配全路径,未匹配到则回退匹配文件名,兼容原有使用习惯 $targetEntries = $zip.Entries | Where-Object { $_.FullName -eq $cleanPath } if ($targetEntries.Count -eq 0) { $targetEntries = $zip.Entries | Where-Object { $_.Name -eq $FileName } } $targetEntries | ForEach-Object { $_.Delete() } Write-Host "$FileName 已从 $ZipFile 中删除" } catch { Write-Host "删除 $ZipFile 中的 $FileName 失败,错误信息:$_" } finally { # 统一释放资源,避免资源泄漏 if ($zip) { $zip.Dispose() } if ($stream) { $stream.Close() $stream.Dispose() } } }
修改点说明
- 自动清理传入路径开头的分隔符,自动替换反斜杠为正斜杠,适配Zip内部路径格式
- 优先匹配全路径,匹配不到时回退匹配文件名,兼容原有使用习惯
- 优化资源释放逻辑,避免未初始化对象报错
2. 优化后的Move-FileToZip函数(自动覆盖旧文件)
无需单独调用删除函数,添加新文件前自动删除对应路径的旧文件,避免重复文件问题:
function Move-FileToZip { param( $ZipFileName, $FileNameInZip, $NewFileToAdd ) $zip = $null try { [Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null $zip = [System.IO.Compression.ZipFile]::Open($ZipFileName, "Update") # 先删除对应路径的旧文件,实现自动覆盖 $cleanPath = $FileNameInZip.TrimStart('/','\').Replace('\','/') $oldEntry = $zip.GetEntry($cleanPath) if ($oldEntry) { $oldEntry.Delete() } [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $NewFileToAdd, $cleanPath, "Optimal") | Out-Null Write-Host "已成功将 $NewFileToAdd 添加到 $ZipFileName 的 $FileNameInZip 路径" } catch { Write-Host "添加 $NewFileToAdd 到 $ZipFileName 失败,错误信息:$_" } finally { if ($zip) { $zip.Dispose() } } }
使用示例
按指定路径删除文件
Remove-FilesFromZip "C:/pathToWar/warFile.war" "/server/lib/file.jar"
导入文件自动覆盖旧版本
Move-FileToZip "C:/pathToWar/warFile.war" "/server/lib/file.jar" "C:/updatedFiles/server/lib/file.jar"
内容的提问来源于stack exchange,提问作者Cezar
相关产品推荐
相关产品推荐

