如何使用PowerShell读取zip文件中的csv文件的内容

时间:2016-06-01 06:55:17

标签: csv powershell zip archive

我有一个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文件中的所有文件

2 个答案:

答案 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() }
    }
}