我正在尝试使用 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
}
我想做的是:
ZipEntry entry = zipInStream.SeekToFile("FileName");
因为我的需求涉及使用 zip 作为包,并且仅根据需要将文件抓取到内存中。
有人熟悉 SharpZipLib 吗?有谁知道我是否可以在不手动完成整个拉链的情况下做到这一点?
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
}
}
var fz1 = new FastZip();
fz1.ExtractZip (string zipFileName, string targetDirectory, string fileFilter)
可以根据文件过滤器(即常规表达式字符串)提取一个或多个文件
这是有关文件过滤器的文档:
// 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$"
因此,对于名为 myfile.dat 的文件,您可以使用“+.*myfile\.dat$”作为文件过滤器。
注意 - 这个答案建议使用 SharpZipLib 的替代方案
DotNetZip 在 ZipFile 类上有一个字符串索引器,使这变得非常简单。
using (ZipFile zip = ZipFile.Read(sourcePath)
{
zip["NameOfFileToUnzip.txt"].Extract();
}
您不需要摆弄输入流和输出流等,只需提取文件即可。另一方面,如果您想要流,您可以获得它:
using (ZipFile zip = ZipFile.Read(sourcePath)
{
Stream s = zip["NameOfFileToUnzip.txt"].OpenReader();
// fiddle with stream here
}
您还可以进行通配符提取。
using (ZipFile zip = ZipFile.Read(sourcePath)
{
// extract all XML files in the archive
zip.ExtractSelectedEntries("*.xml");
}
有重载来指定覆盖/不覆盖、不同的目标目录等。您还可以根据文件名以外的标准进行提取。 例如,提取 2009 年 1 月 15 日之后的所有文件:
// extract all files modified after 15 Jan 2009
zip.ExtractSelectedEntries("mtime > 2009-01-15");
您可以组合标准:
// 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");
您不必提取您选择的文件。您只需选择它们,然后决定是否提取即可。
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();
}
}
我获得了 VB.NET 的一个选项,可以从 Zip 存档器中提取特定文件。西班牙语评论。获取 Zip 文件路径、要提取的文件名、密码(如果需要)。如果 OriginalPath 设置为 1,则提取到原始路径;如果 OriginalPath=0,则使用 DestPath。密切关注“ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream”内容...
如下:
''' <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
FileStream fileStreamIn = new FileStream(fileNameZipped, FileMode.Open, FileAccess.Read);
ZipInputStream zipInStream = new ZipInputStream(fileStreamIn);
using (var zf = new ZipFile(fileStreamIn))
{
//zf.Password = "123";
var ze = zf.GetEntry(fileName);
if (ze == null)
{
throw new ArgumentException(fileName, "not found in Zip");
}
using (var s = zf.GetInputStream(ze))
{
byte[] buffer = new byte[ze.Size];
s.Read(buffer, 0, (int) ze.Size);
//string textdata = Encoding.Default.GetString(buffer)
}
}