Quick question: I need to extract zip file and have a certain file extract last.
More info: I know how to extract a zip file with c# (fw 4.5).
The problem I'm having now is that I have a zip file and inside it there is always a file name (for example) "myFlag.xml" and a few more files.
Since I need to support some old applications that listen to the folder I'm extracting to, I want to make sure that the XML file will always be extract the last.
Is there some thing like "exclude" for the zip function that can extract all but a certain file so I can do that and then extract only the file alone?
Thanks.
You could probably try a foreach loop on the ZipArchive, and exclude everything that doesn't match your parameters, then, after the loop is done, extract the last file.
Something like this:
private void TestUnzip_Foreach()
{
using (ZipArchive z = ZipFile.Open("zipfile.zip", ZipArchiveMode.Read))
{
string LastFile = "lastFileName.ext";
int curPos = 0;
int lastFilePosition = 0;
foreach (ZipArchiveEntry entry in z.Entries)
{
if (entry.Name != LastFile)
{
entry.ExtractToFile(#"C:\somewhere\" + entry.FullName);
}
else
{
lastFilePosition = curPos;
}
curPos++;
}
z.Entries[lastFilePosition].ExtractToFile(#"C:\somewhere_else\" + LastFile);
}
}
I'm using the DotNetZip library to extract files from a zip file.
using(ZipFile zip = ZipFile.Read(zipLocation))
{
foreach (ZipEntry entry in zip){
entry.Extract(_updateDir);
Log.Write("Unpacked: " + entry.FileName, Log.LogType.Info);
}
zip.Dispose();
}
Later on, I attempt to edit one of the files that I extracted.
var updateList = allFiles.Where(x => x.Contains(".UPD"));
foreach (string upd in updateList){
string[] result = File.ReadAllLines(upd);
int index = Array.IndexOf(result, "[Info]");
//then I do stuff with index
}
At the line
string[] result = File.ReadAllLines(upd);
I get the exception: The process cannot access the file <file name> because it is being used by another process.
I know that this exception is being thrown because the file is in use elsewhere. The only place it is in use before File.ReadAllLines(upd) is in the DotNetZip code above.
Is there a way in the DotNetZip code to prevent this from happening?
The problem it's not from DotNetZip. I tried the code in my project and it works file:
[Test]
public void Test2()
{
using (ZipFile zip = ZipFile.Read("D:/ArchiveTest.zip"))
{
foreach (ZipEntry entry in zip)
{
entry.Extract("D:/ArchiveTest");
}
zip.Dispose();
}
var updateList = Directory.GetFiles("D:/ArchiveTest").Where(x => x.Contains(".UPD"));
foreach (string upd in updateList)
{
string[] result = File.ReadAllLines(upd);
int index = Array.IndexOf(result, "[Info]");
//then I do stuff with index
}
}
Probably another process is using the file you are trying to read. If you have Windows7 or Windows8, you can use the built-in Resource Monitor. Read this post: How to know what process is using a given file?
I have a file upload control.
I restrict users to upload only zip files.
the namespace i use is Ionic.Zip;
I also want check if that zip file has a folder inside.
I have to restrict the users not upload a zipfile with a folder inside.
I could check how many files inside zip file like
using (ZipFile zip = ZipFile.Read(file_path))
{
if (zip.Count < 5)
{
}
I do not know how to check for a folder inside
Anyone can help me please.
thanks in advance
void Main()
{
var isGood=false;
using (ZipFile zip = new ZipFile(#"c:\\1.zip"))
{
for (var i=0;i<zip.Count;i++)
if (zip[i].Attributes==FileAttributes.Directory)
{
isGood=false;
break;
}
}
if (isGood) Console.WriteLine ("ok");
else
Console.WriteLine ("error");
}
// Define other methods and classes here
edit :
there's seems to be a problem with the way you created this zip file.
I extracted the files from the file you sent me and created new zip : (named 3.zip):
and as you can see - the code works :
so I guess the dll is not powerful enough to recognize edge format
You can iterate on your zip object's ZipEntries - ZipEntry object contains IsDirectory property.
foreach(var entry in zip)
{
if(entry.IsDirectory)
{
//your stuff
}
}
I did this simple code with the latest version of the library DotNetZip, for some reason when I add a file I get all the folder structure. For example if I add:
C:\one folder\two folders\File.doc
Inside the zip file I will have
one folder\two folders\File.doc
But my expected result would be to have just the file.doc
This is my code, I don't know if I am doing something wrong or what..:
//C#
public static void MethodOne(string PathInput, int LimitKb=0, bool DeleteInput=false)
{
using (ZipFile zip = new ZipFile())
{
//add file to zip
zip.AddFile(PathInput);
//save it
zip.Save(PathInput + ".zip");
}
}
Thanks! :)
Use the overloaded, two-parameter call to AddFile where you specify the internal directory structure.
zip.AddFile(filename, String.Empty);
I think that would do what you want but I can't easily test it.
I like to zip multiple files which are being created dynamically in my web application. Those files should be zipped. For this, i dont want to use any third-party tools. just like to use .net api in c#
With the release of the .NET Framework 4.5 this is actually a lot easier now with the updates to System.IO.Compression which adds the ZipFile class. There is a good walk-through on codeguru; however, the basics are in line with the following example:
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.IO.Compression.FileSystem;
namespace ZipFileCreator
{
public static class ZipFileCreator
{
/// <summary>
/// Create a ZIP file of the files provided.
/// </summary>
/// <param name="fileName">The full path and name to store the ZIP file at.</param>
/// <param name="files">The list of files to be added.</param>
public static void CreateZipFile(string fileName, IEnumerable<string> files)
{
// Create and open a new ZIP file
var zip = ZipFile.Open(fileName, ZipArchiveMode.Create);
foreach (var file in files)
{
// Add the entry for each file
zip.CreateEntryFromFile(file, Path.GetFileName(file), CompressionLevel.Optimal);
}
// Dispose of the object when we are done
zip.Dispose();
}
}
}
Use System.IO.Packaging in .NET 3.0+.
See this introduction to System.IO.Packaging
If you're able to take a .NET 4.5 dependency, there's a System.IO.Compression.ZipArchive in that universe; see walkthrough article here (via InfoQ news summary article here)
Simple zip file with flat structure:
using System.IO;
using System.IO.Compression;
private static void CreateZipFile(IEnumerable<FileInfo> files, string archiveName)
{
using (var stream = File.OpenWrite(archiveName))
using (ZipArchive archive = new ZipArchive(stream, System.IO.Compression.ZipArchiveMode.Create))
{
foreach (var item in files)
{
archive.CreateEntryFromFile(item.FullName, item.Name, CompressionLevel.Optimal);
}
}
}
You need to add reference to System.IO.Compression and System.IO.Compression.FileSystem
I'm not sure what you mean by not wanting to use thrid party tools, but I assume its that you don't want some nasty interop to programmatically do it through another piece of software.
I recommend using ICSharpCode SharpZipLib
This can be added to your project as a reference DLL and is fairly straightforward for creating ZIP files and reading them.
Well you can zip the files using following function you have to just pass the file bytes and this function will zip the file bytes passed as parameter and return the zipped file bytes.
public static byte[] PackageDocsAsZip(byte[] fileBytesTobeZipped, string packageFileName)
{
try
{
string parentSourceLoc2Zip = #"C:\UploadedDocs\SG-ACA OCI Packages";
if (Directory.Exists(parentSourceLoc2Zip) == false)
{
Directory.CreateDirectory(parentSourceLoc2Zip);
}
//if destination folder already exists then delete it
string sourceLoc2Zip = string.Format(#"{0}\{1}", parentSourceLoc2Zip, packageFileName);
if (Directory.Exists(sourceLoc2Zip) == true)
{
Directory.Delete(sourceLoc2Zip, true);
}
Directory.CreateDirectory(sourceLoc2Zip);
FilePath = string.Format(#"{0}\{1}",
sourceLoc2Zip,
"filename.extension");//e-g report.xlsx , report.docx according to exported file
File.WriteAllBytes(FilePath, fileBytesTobeZipped);
//if zip already exists then delete it
if (File.Exists(sourceLoc2Zip + ".zip"))
{
File.Delete(sourceLoc2Zip + ".zip");
}
//now zip the source location
ZipFile.CreateFromDirectory(sourceLoc2Zip, sourceLoc2Zip + ".zip", System.IO.Compression.CompressionLevel.Optimal, true);
return File.ReadAllBytes(sourceLoc2Zip + ".zip");
}
catch
{
throw;
}
}
Now if you want to export this zip bytes created for user to download you can call this function using following lines
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=Report.zip");
Response.ContentType = "application/zip";
Response.BinaryWrite(PackageDocsAsZip(fileBytesToBeExported ,"TemporaryFolderName"));
Response.End();
You could always call a third-party executable like 7-zip with an appropriate command line using the System.Diagnostics.Process class. There's no interop that way because you're just asking the OS to launch a binary.
DotNetZip is the way to go (dotnetzip.codeplex.com)... don't try the .NET Packaging library.. too hard to use and the [Content_Types].xml that it puts in there bothers me..
Check out System.IO.Compression.DeflateStream. The linked documentation page also offers an example.