我有一个zip文件,其中包含几个CSV文件。如何在不使用PowerShell提取zip文件的情况下阅读这些CSV文件的内容?
我一直在使用Read-Archive
Cmdlet作为PowerShell Community Extensions (PSCX)
这是我到目前为止所尝试过的。
$path = "$env:USERPROFILE\Downloads\"
$fullpath = Join-Path $path filename.zip
Read-Archive $fullpath | Foreach-Object {
Get-Content $_.Name
}
但是当我运行代码时,我收到此错误消息 Get-Content:指定路径filename.csv中的对象不存在,或者已被-Include或-Exclude参数过滤。
但是,当我运行Read-Archive $fullpath
时,它会列出zip文件中的所有文件
答案 0 :(得分:15)
有多种方法可以实现这一目标:
<强> 1。以下是使用Ionic.zip dll的示例:
clear
Add-Type -Path "E:\sw\NuGet\Packages\DotNetZip.1.9.7\lib\net20\Ionic.Zip.dll"
$zip = [Ionic.Zip.ZipFile]::Read("E:\E.zip")
$file = $zip | where-object { $_.FileName -eq "XMLSchema1.xsd"}
$stream = new-object IO.MemoryStream
$file.Extract($stream)
$stream.Position = 0
$reader = New-Object IO.StreamReader($stream)
$text = $reader.ReadToEnd()
$text
$reader.Close()
$stream.Close()
$zip.Dispose()
它按名称选择文件(XMLSchema1.xsd)并将其提取到内存流中。然后,您需要将内存流读取为您喜欢的内容(在我的示例中为字符串)。
<强> 2。在Powershell 5中,您可以使用Expand-Archive
,请参阅:https://technet.microsoft.com/en-us/library/dn841359.aspx?f=255&MSPPError=-2147217396
它会将整个档案提取到一个文件夹中:
Expand-Archive "E:\E.zip" "e:\t"
请记住,提取整个存档需要时间,然后您必须清理临时文件
第3。还有一种方法可以只提取1个文件:
$shell = new-object -com shell.application
$zip = $shell.NameSpace("E:\E.zip")
$file = $zip.items() | Where-Object { $_.Name -eq "XMLSchema1.xsd"}
$shell.Namespace("E:\t").copyhere($file)
<强> 4。还有一种使用原生方式的方式:
Add-Type -assembly "system.io.compression.filesystem"
$zip = [io.compression.zipfile]::OpenRead("e:\E.zip")
$file = $zip.Entries | where-object { $_.Name -eq "XMLSchema1.xsd"}
$stream = $file.Open()
$reader = New-Object IO.StreamReader($stream)
$text = $reader.ReadToEnd()
$text
$reader.Close()
$stream.Close()
$zip.Dispose()
答案 1 :(得分:0)
基于Andrey的4.解决方案,我提出以下功能:
(请记住,“ ZipFile”类从.NET Framework 4.5开始存在)
Add-Type -assembly "System.IO.Compression.FileSystem"
function Read-FileInZip($ZipFilePath, $FilePathInZip) {
try {
if (![System.IO.File]::Exists($ZipFilePath)) {
throw "Zip file ""$ZipFilePath"" not found."
}
$Zip = [System.IO.Compression.ZipFile]::OpenRead($ZipFilePath)
$ZipEntries = [array]($Zip.Entries | where-object {
return $_.FullName -eq $FilePathInZip
});
if (!$ZipEntries -or $ZipEntries.Length -lt 1) {
throw "File ""$FilePathInZip"" couldn't be found in zip ""$ZipFilePath""."
}
if (!$ZipEntries -or $ZipEntries.Length -gt 1) {
throw "More than one file ""$FilePathInZip"" found in zip ""$ZipFilePath""."
}
$ZipStream = $ZipEntries[0].Open()
$Reader = [System.IO.StreamReader]::new($ZipStream)
return $Reader.ReadToEnd()
}
finally {
if ($Reader) { $Reader.Dispose() }
if ($Zip) { $Zip.Dispose() }
}
}