.net 使用 SharpZipLib 解压缩特定文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/328343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:42:37  来源:igfitidea点击:

Using SharpZipLib to unzip specific files?

.netcompressionsharpziplib

提问by FlySwat

I'm trying to use SharpZipLib to pull specified files from a zip archive. All of the examples I've seen always expect that you want to unzip the entire zip, and do something along the lines of:

我正在尝试使用 SharpZipLib 从 zip 存档中提取指定的文件。我见过的所有示例都希望您解压缩整个 zip,然后执行以下操作:

       FileStream fileStreamIn = new FileStream (sourcePath, FileMode.Open, FileAccess.Read);

        ZipInputStream zipInStream = new ZipInputStream(fileStreamIn);
        ZipEntry entry;

        while (entry = zipInStream.GetNextEntry() != null)
        {
            // Unzip file
        }

What I want to do is something like:

我想做的是:

ZipEntry entry = zipInStream.SeekToFile("FileName");

As my needs involve using a zip as a package and only grabbing files into memory as needed.

因为我的需要涉及使用 zip 作为包,并且只根据需要将文件抓取到内存中。

Is anyone familiar with SharpZipLib? Does anyone know if I can do this without running through the entire zip by hand?

有人熟悉SharpZipLib吗?有谁知道我是否可以在不用手穿过整个拉链的情况下做到这一点?

回答by Mark Brackett

ZipFile.GetEntry should do the trick:

ZipFile.GetEntry 应该可以解决问题:

using (var fs = new FileStream(sourcePath, FileMode.Open, FileAccess.Read))
using (var zf = new ZipFile(fs)) {
   var ze = zf.GetEntry(fileName);
   if (ze == null) {
      throw new ArgumentException(fileName, "not found in Zip");
   }

   using (var s = zf.GetInputStream(ze)) {
      // do something with ZipInputStream
   }
}

回答by Todd Smith

FastZip.ExtractZip (string zipFileName, string targetDirectory, string fileFilter)

can extract one or more files based on a file filter (ie regular expressoin string)

可以根据文件过滤器(即正则表达式字符串)提取一个或多个文件

Here's the doc regarding the file filter:

这是关于文件过滤器的文档:

// A filter is a sequence of independant <see cref="Regex">regular expressions</see> separated by semi-colons ';'
// Each expression can be prefixed by a plus '+' sign or a minus '-' sign to denote the expression
// is intended to include or exclude names.  If neither a plus or minus sign is found include is the default
// A given name is tested for inclusion before checking exclusions.  Only names matching an include spec
// and not matching an exclude spec are deemed to match the filter.
// An empty filter matches any name.
// </summary>
// <example>The following expression includes all name ending in '.dat' with the exception of 'dummy.dat'
// "+\.dat$;-^dummy\.dat$"

so for a file named myfile.dat you could use "+.*myfile\.dat$" as your file filter.

因此,对于名为 myfile.dat 的文件,您可以使用“+.*myfile\.dat$”作为文件过滤器。

回答by Cheeso

Note - this answer suggests an alternative to SharpZipLib

注意 - 这个答案提出了 SharpZipLib 的替代方案



DotNetZiphas a string indexer on the ZipFile class to make this really easy.

DotNetZip在 ZipFile 类上有一个字符串索引器,使这非常容易。

 using (ZipFile zip = ZipFile.Read(sourcePath)
 {
   zip["NameOfFileToUnzip.txt"].Extract();
 }

You don't need to fiddle with inputstreams and outputstreams and so on, just to extract a file. On the other hand if you want the stream, you can get it:

您不需要摆弄输入流和输出流等,只需提取文件即可。另一方面,如果你想要流,你可以得到它:

 using (ZipFile zip = ZipFile.Read(sourcePath)
 {
   Stream s = zip["NameOfFileToUnzip.txt"].OpenReader();
   // fiddle with stream here
 }

You can also do wildcard extractions.

您还可以进行通配符提取。

 using (ZipFile zip = ZipFile.Read(sourcePath)
 {
     // extract all XML files in the archive
     zip.ExtractSelectedEntries("*.xml");
 }

There are overloads to specify overwrite/no-overwrite, different target directories, etc. You can also extract based on criteria other than the filename. For example, extract all files newer than January 15, 2009:

有重载来指定覆盖/不覆盖、不同的目标目录等。您还可以根据文件名以外的条件进行提取。例如,提取 2009 年 1 月 15 日之后的所有文件:

     // extract all files modified after 15 Jan 2009
     zip.ExtractSelectedEntries("mtime > 2009-01-15");

And you can combine criteria:

您可以组合条件:

     // extract all files that are modified after 15 Jan 2009) AND  larger than 1mb
     zip.ExtractSelectedEntries("mtime > 2009-01-15 and size > 1mb");

     // extract all XML files that are modified after 15 Jan 2009) AND  larger than 1mb
     zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15 and size > 1mb");

You don't have to extract the files that you select. You can just select them and then make decisions on whether to extract or not.

您不必解压缩您选择的文件。您可以选择它们,然后决定是否提取。

    using (ZipFile zip1 = ZipFile.Read(ZipFileName))
    {
        var PhotoShopFiles = zip1.SelectEntries("*.psd");
        // the selection is just an ICollection<ZipEntry>
        foreach (ZipEntry e in PhotoShopFiles)
        {
            // examine metadata here, make decision on extraction
            e.Extract();
        }
    }

回答by Cheeso

I get an option to VB.NET, to extract specific files from Zip archivers. Comments in Spanish. Take a Zip file path, Filename you want extracted, password if needed. Extract to original path if OriginalPath is setted to 1, or use DestPath if OriginalPath=0. Keep an eye in "ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream" stuff...

我可以选择 VB.NET,从 Zip 存档器中提取特定文件。西班牙语评论。获取 Zip 文件路径、要提取的文件名、密码(如果需要)。如果 OriginalPath 设置为 1,则提取到原始路径,如果 OriginalPath=0,则使用 DestPath。密切关注“ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream”的内容...

It's as follows:

如下:

''' <summary>
''' Extrae un archivo específico comprimido dentro de un archivo zip
''' </summary>
''' <param name="SourceZipPath"></param>
''' <param name="FileName">Nombre del archivo buscado. Debe incluir ruta, si se comprimió usando guardar con FullPath</param>
''' <param name="DestPath">Ruta de destino del archivo. Ver parámetro OriginalPath.</param>
''' <param name="password">Si el archivador no tiene contrase?a, puede quedar en blanco</param>
''' <param name="OriginalPath">OriginalPath=1, extraer en la RUTA ORIGINAL. OriginalPath=0, extraer en DestPath</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function ExtractSpecificZipFile(ByVal SourceZipPath As String, ByVal FileName As String, _
ByVal DestPath As String, ByVal password As String, ByVal OriginalPath As Integer) As Boolean
    Try
        Dim fileStreamIn As FileStream = New FileStream(SourceZipPath, FileMode.Open, FileAccess.Read)
        Dim fileStreamOut As FileStream
        Dim zf As ZipFile = New ZipFile(fileStreamIn)

        Dim Size As Integer
        Dim buffer(4096) As Byte

        zf.Password = password

        Dim Zentry As ZipEntry = zf.GetEntry(FileName)

        If (Zentry Is Nothing) Then
            Debug.Print("not found in Zip")
            Return False
            Exit Function
        End If

        Dim fstr As ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream
        fstr = zf.GetInputStream(Zentry)

        If OriginalPath = 1 Then
            Dim strFullPath As String = Path.GetDirectoryName(Zentry.Name)
            Directory.CreateDirectory(strFullPath)
            fileStreamOut = New FileStream(strFullPath & "\" & Path.GetFileName(Zentry.Name), FileMode.Create, FileAccess.Write)
        Else
            fileStreamOut = New FileStream(DestPath + "\" + Path.GetFileName(Zentry.Name), FileMode.Create, FileAccess.Write)
        End If


        Do
            Size = fstr.Read(buffer, 0, buffer.Length)
            fileStreamOut.Write(buffer, 0, Size)
        Loop While (Size > 0)

        fstr.Close()
        fileStreamOut.Close()
        fileStreamIn.Close()
        Return True
    Catch ex As Exception
        Return False
    End Try

End Function