How to List the Contents of a .Zip Folder in C#

how to find an entity in zip file is file or directory in c#

This functionality is available out of the box in .Net Framework 4.5 and later. You have to use this library:

using System.IO.Compression;

And then you'll be able to do this:

string zipPath = @"c:\example\start.zip";
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith('\'))
Console.WriteLine($"{entry.FullName} is a directory.");
else
Console.WriteLine($"{entry.FullName} is a file.");
}
}

See here for more details:

How to list the contents of a .zip folder in c#?

How get file list from .zip archive and copy the contents into a ListView?

As already mentioned in the comments you can use a library for that.

.NET already has one for handling compressed zip archives called System.IO.Compression.ZipFile integrated into the .NET framework. See the MSDN.

Use this to open the .zip file (read-only) via ZipFile.OpenRead and ZipFile.Entries property to get a list of file information within the archive.

Entries is a collection of ZipFile.ZipArchiveEntry which contains a few public properties you can access. Namely the ones we need are:

  • FullName
  • LastWriteTime
  • Length

Full sample code:

using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
ListViewItem txtItem = new ListViewItem(entry.FullName);
txtItem .SubItems.Add(entry.LastWriteTime);
txtItem .SubItems.Add(entry.Length); //Uncompressed size
listView.Items.Add(txtItem);
}
}
}

Put this into your Button_Click event and you're good to go.

C# - Count all Files in directory including Zip in Zip etc

One way of accomplishing it is extracting all the zips to a temporary folder recursively and then count for non-zip files inside of those directories. Once we get the count we can delete the intermediate files and revert the system to initial state. Remember the user needs to have write permissions on the file system to run the code in that particular directory.

using System;
using System.IO;
using System.IO.Compression;

namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{

DirectoryInfo directoryInfo = new DirectoryInfo(@"C:\Temp");

ProcessDirectory(directoryInfo); // Process the directory and extract any zip files.

int count = 0;
foreach (DirectoryInfo subdirectory in directoryInfo.EnumerateDirectories())
{
if (subdirectory.Name.EndsWith(".ExtractedFiles")) // Count only extracted zip files in root directory.
{
count = CountFiles(subdirectory, count);
}
}

DeleteIntermediateFiles(directoryInfo); // Delete the extracted files.

Console.WriteLine(count);
}

public static void ProcessDirectory(DirectoryInfo directoryInfo)
{
foreach (DirectoryInfo subdirectory in directoryInfo.EnumerateDirectories())
{
ProcessDirectory(subdirectory); //Process subdirectories.
}

ProcessFiles(directoryInfo); //Process files.
}

private static void ProcessFiles(DirectoryInfo directoryInfo)
{
foreach (FileInfo file in directoryInfo.EnumerateFiles())
{
if (file.Extension.Equals(".zip")) // extract zip files.
{
var extractFilesDirectory = directoryInfo.CreateSubdirectory(
Path.GetFileNameWithoutExtension(file.Name) + ".ExtractedFiles");
ZipFile.ExtractToDirectory(file.FullName, extractFilesDirectory.FullName);
ProcessDirectory(extractFilesDirectory); //process extracted files.
}
}
}

public static int CountFiles(DirectoryInfo directoryInfo, int count)
{
foreach (DirectoryInfo subdirectory in directoryInfo.EnumerateDirectories())
{
count = CountFiles(subdirectory, count);
}

foreach (var fileInfo in directoryInfo.GetFiles())
{
if (fileInfo.Extension != ".zip") //exclude zip files while counting.
count++;
}

return count;
}

public static void DeleteIntermediateFiles(DirectoryInfo directoryInfo)
{
foreach (DirectoryInfo subdirectory in directoryInfo.EnumerateDirectories())
{
if (subdirectory.Name.EndsWith(".ExtractedFiles"))
{
Directory.Delete(subdirectory.FullName, true);
}
}
}
}
}

How to read data from a zip file without having to unzip the entire file

DotNetZip is your friend here.

As easy as:

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
ZipEntry e = zip["MyReport.doc"];
e.Extract(OutputStream);
}

(you can also extract to a file or other destinations).

Reading the zip file's table of contents is as easy as:

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
foreach (ZipEntry e in zip)
{
if (header)
{
System.Console.WriteLine("Zipfile: {0}", zip.Name);
if ((zip.Comment != null) && (zip.Comment != ""))
System.Console.WriteLine("Comment: {0}", zip.Comment);
System.Console.WriteLine("\n{1,-22} {2,8} {3,5} {4,8} {5,3} {0}",
"Filename", "Modified", "Size", "Ratio", "Packed", "pw?");
System.Console.WriteLine(new System.String('-', 72));
header = false;
}
System.Console.WriteLine("{1,-22} {2,8} {3,5:F0}% {4,8} {5,3} {0}",
e.FileName,
e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
e.UncompressedSize,
e.CompressionRatio,
e.CompressedSize,
(e.UsesEncryption) ? "Y" : "N");

}
}

Edited To Note: DotNetZip used to live at Codeplex. Codeplex has been shut down. The old archive is still available at Codeplex. It looks like the code has migrated to Github:

  • https://github.com/DinoChiesa/DotNetZip. Looks to be the original author's repo.
  • https://github.com/haf/DotNetZip.Semverd. This looks to be the currently maintained version. It's also packaged up an available via Nuget at https://www.nuget.org/packages/DotNetZip/

Enumerate zipped contents of unzipped folder

GetDirectories is the wrong thing to use. Explorer lies to you; zip files are actually files with an extension .zip, not real directories on the file system level.

Look at:
https://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive.entries%28v=vs.110%29.aspx (ZipArchive.Entries) and/or
https://msdn.microsoft.com/en-us/library/system.io.compression.zipfile%28v=vs.110%29.aspx (ZipFile) to see how to deal with them.

List files inside ZIP file located on SFTP server in C#

With SSH.NET library, it could be as easy as:

using (var client = new SftpClient(host, username, password)
{
client.Connect();

using (Stream stream = client.OpenRead("/remote/path/archive.zip"))
using (var archive = new ZipArchive(stream, ZipArchiveMode.Read))
{
foreach (var entry in archive.Entries)
{
Console.WriteLine(entry);
}
}
}

You need to reference System.IO.Compression assembly to get the ZipArchive.

The code will only read (download) the ZIP central directory record, not whole ZIP archive. For a proof, see the end of the answer.


Unfortunately, there's a bug in the library. To workaround it, you have to implement a wrapper Stream implementation like this:

class FixStream : Stream
{
public override long Seek(long offset, SeekOrigin origin)
{
long result;
// workaround for SSH.NET bug in implementation of SeekOrigin.End
if (origin == SeekOrigin.End)
{
result = _stream.Seek(Length + offset, SeekOrigin.Begin);
}
else
{
result = _stream.Seek(offset, origin);
}
return result;
}

// passthrough implementation of the rest of Stream interface

public override bool CanRead => _stream.CanRead;

public override bool CanSeek => _stream.CanSeek;

public override bool CanWrite => _stream.CanWrite;

public override long Length => _stream.Length;

public override long Position {
get => _stream.Position; set => _stream.Position = value; }

public FixStream(Stream stream)
{
_stream = stream;
}

public override void Flush()
{
_stream.Flush();
}

public override int Read(byte[] buffer, int offset, int count)
{
return _stream.Read(buffer, offset, count);
}

public override void SetLength(long value)
{
_stream.SetLength(value);
}

public override void Write(byte[] buffer, int offset, int count)
{
_stream.Write(buffer, offset, count);
}

private Stream _stream;
}

And wrap the SftpFileStream to it:

using (Stream stream = client.OpenRead("/remote/path/archive.zip"))
using (var stream2 = new FixStream(stream))
using (var archive = new ZipArchive(stream2, ZipArchiveMode.Read))
{
...
}

As a proof that it really works, I've added logging to all methods of FixStream. When using the code with 18 MB (18265315 bytes) ZIP archive with two entries, the following was produced. So only 244 bytes were read from the stream. Actually more is read from the actual remote SFTP file, as SSH.NET buffers the reads (otherwise the code would be quite ineffective, particularly in this case, as you can see that ZipArchive does lot of small reads). The default SSH.NET buffer is 32 KB (SftpClient.BufferSize).

Tried to seek to -18 from End => converting to seek to 18265297 from Begin
Seeked to 18265297 from Begin => 18265297
Seeked to -32 from Current => 18265265
Tried to read 32, got 32
Seeked to -32 from Current => 18265265
Seeked to 28 from Current => 18265293
Tried to read 4, got 4
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 2, got 2
Seeked to 18265075 from Begin => 18265075
Tried to read 4, got 4
Tried to read 1, got 1
Tried to read 1, got 1
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 28, got 28
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 32, got 32
Set position to 18265185
Tried to read 4, got 4
Tried to read 1, got 1
Tried to read 1, got 1
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 4, got 4
Tried to read 4, got 4
Tried to read 26, got 26
Tried to read 2, got 2
Tried to read 2, got 2
Tried to read 32, got 32
Set position to 18265293
Tried to read 4, got 4

ExtractToDirectory , how to extract a zip folder within a zip folder using c#

As per what I see in your code, I think you should call the extractZipFiles method recursively, so that after the extracting you call the method again with the directory where you extracted the files so it scans it for *.zip files.

I'm not sure about what variables you'd want to use, but something like this:

public void extractZipFiles(string targetFileDirectory, string zipFileDirectory, string Number)
{
Directory.GetFiles(zipFileDirectory, "*.zip", SearchOption.AllDirectories).ToList()
.ForEach(zipFilePath => {
var test = Number + "_" + Path.GetFileNameWithoutExtension(zipFilePath);
var extractPathForCurrentZip = Path.Combine(targetFileDirectory, test);
if(!Directory.Exists(extractPathForCurrentZip))
{
Directory.CreateDirectory(extractPathForCurrentZip);
}
ZipFile.ExtractToDirectory(zipFilePath, extractPathForCurrentZip);
extractZipFiles(targetFileDirectory, extractPathForCurrentZip, Number);
});
}

Create zip file from all files in folder

Referencing System.IO.Compression and System.IO.Compression.FileSystem in your Project

using System.IO.Compression;

string startPath = @"c:\example\start";//folder to add
string zipPath = @"c:\example\result.zip";//URL for your ZIP file
ZipFile.CreateFromDirectory(startPath, zipPath, CompressionLevel.Fastest, true);
string extractPath = @"c:\example\extract";//path to extract
ZipFile.ExtractToDirectory(zipPath, extractPath);

To use files only, use:

//Creates a new, blank zip file to work with - the file will be
//finalized when the using statement completes
using (ZipArchive newFile = ZipFile.Open(zipName, ZipArchiveMode.Create))
{
foreach (string file in Directory.GetFiles(myPath))
{
newFile.CreateEntryFromFile(file, System.IO.Path.GetFileName(file));
}
}


Related Topics



Leave a reply



Submit