Creating Directories in a ZipArchive C# .Net 4.5
You can use something like the following, in other words, create the directory structure by hand:
using (var fs = new FileStream("1.zip", FileMode.Create))
using (var zip = new ZipArchive(fs, ZipArchiveMode.Create))
{
zip.CreateEntry("12/3/"); // just end with "/"
}
Adding a directory to an existing .zip file
I managed to find a way to do this thanks to @stuartd. He pointed me to this answer https://stackoverflow.com/a/22339337/3182972 and I found a way to implement it into my code that creates directories with files inside them from a source location of said directories.
Here is the code:
using (FileStream zipToOpen = new FileStream("c:\MyDestination\test.zip", FileMode.Open))
{
using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
{
ZipArchiveEntry readmeEntry;
DirectoryInfo d = new DirectoryInfo(c:\MySourceFolder);
FileInfo[] Files = d.GetFiles("*");
foreach (FileInfo file in Files)
{
readmeEntry = archive.CreateEntryFromFile("c:\MySourceFolder"+ "\\" + file.Name, "MySourceFolder" + "/" + file.Name);
}
}
}
So what I did was go to my source directory and went through all of the files that are there and with a foreach cycle I added them to the destination folder in the zip file.
You can also get the source directory name with this code:
string sourcepath = "C:\MySourceFolder";
int ind = sourcepath.LastIndexOf("\\") + 1;
string folderName = sourcepath.Substring(ind, folder.Length - ind);
Directory.CreateDirectory() does not create folder within ZipFile
Edited:
If you are looking for more control, you can just create a function that adds files to a zip archive. You can then use recursion to add any subfolders and files.
First you can define a function that accepts a zip archive to add files to:
public void AddFolderToZip(ZipArchive archive, string rootPath, string path, bool recursive)
{
foreach (var filePath in Directory.GetFiles(path))
{
//Remove root path portion from file path, so entry is relative to root
string entryName = filePath.Replace(rootPath, "");
entryName = entryName.StartsWith("\\") ? entryName.Substring(1) : entryName;
var entry = archive.CreateEntryFromFile(filePath, entryName);
}
if (recursive)
{
foreach (var subPath in Directory.GetDirectories(path))
{
AddFolderToZip(archive, rootPath, subPath, recursive);
}
}
}
Then you can call it using the following code:
string strStartPath = @"C:\Test\zip";
string strZipPath = @"C:\Test\output.zip";
ZipArchive archive = ZipFile.Open(strZipPath, ZipArchiveMode.Create);
bool recursive = true;
foreach (var directoryPath in Directory.GetDirectories(strStartPath))
{
AddFolderToZip(archive, strStartPath, directoryPath, recursive);
}
archive.Dispose();
This code adds each directory it finds in a top level directory. And for each directory it finds, it will use recursion to add any subdirectories or files found within those.
Can I maintain directory structure when zipping file?
@ErocM the link provided by @Flydog57 gives you exactly what you want. You are not exploiting the entryName
argument correctly (the second argument in your case when calling CreateEntryFromFile
).
Independently of which file you are adding to the archive (from same of different folders), you have to structure your archive using the entryName
argument the C# api gives to you.
If your file's fullname is /tmp/myfile.txt
, and you do archive.CreateEntryFromFile(item.FullName, item.Name)
, then the archive entry name will be myfile.txt
. No folder created as the entry name doesn't contain folder structure in it's name.
However, if you call archive.CreateEntryFromFile(item.FullName, item.FullName)
, you will then have you file folder structure into the archive.
You can try with your function just changing item.Name
into item.FullName
.
Just be careful, on windows; if you path is C:\tmp\myfile.txt
for instance, the archive will not be extractable correctly. You can then add some little code to remove C:
from the full name of your files.
Some examples taking your implementation:
using System;
using System.IO;
using System.Collections.Generic;
using System.IO.Compression;
namespace ConsoleApp
{
internal class Program
{
static void Main(string[] args)
{
FileInfo f1 = new FileInfo(@"/tmp/test1.txt");
FileInfo f2 = new FileInfo(@"/tmp/testdir/test2.txt");
List<FileInfo> files = new();
files.Add(f1);
files.Add(f2);
CreateZipFile(files, @"/tmp/archive.zip");
}
public static void CreateZipFile(IEnumerable<FileInfo> files, string archiveName)
{
using (var stream = File.OpenWrite(archiveName))
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var item in files)
{
// Here for instance, I put all files in the input list in the same directory, without checking from where they are in the host file system.
archive.CreateEntryFromFile(item.FullName, $"mydir/{item.Name}", CompressionLevel.Optimal);
// Here, I am just using the actual full path of the file. Be careful on windows with the disk name prefix (C:, D:, etc...).
// archive.CreateEntryFromFile(item.FullName, item.FullName, CompressionLevel.Optimal);
}
}
}
}
Zipping files in .NET 4.5
Try this:
using (FileStream fs = new FileStream(@"C:\Temp\myZip.zip",FileMode.Create))
using (ZipArchive za = new ZipArchive(fs, ZipArchiveMode.Create))
{
za.CreateEntryFromFile(@"C:\Temp\myFile.txt", "myFile.txt");
}
Related Topics
Is the C# Compiler Smart Enough to Optimize This Code
PDF Compression with Itextsharp
Changing Font for Richtextbox Without Losing Formatting
Sending an Array of Values to Oracle Procedure to Use in Where in Clause
How Can Xml Documentation for Web API Include Documentation from Beyond the Main Project
Convert Array of Integers to Comma-Separated String
How to Create a Friendly Url in ASP.NET MVC
How to Get All the Ad Groups for a Particular User
Any Way to Turn the "Internet Off" in Windows Using C#
Parent Control Mouse Enter/Leave Events with Child Controls
C# Array.Findallindexof Which Findall Indexof
Curiously Recurring Template Pattern and Generics Constraints (C#)
Converting ASP.NET MVC Razor @Helper Function into a Method of a Helper Class
Get Values from Process Standardoutput
.Net Core Identity Server 4 Authentication VS Identity Authentication