I have a question according to the ZipArchive Library in System.IO.Compression.
I want to create an uncompressed .zip file. My code so far looks like this:
//Creates a "Deflate"-Mode file in the created zip.
using (FileStream fs = new FileStream(zippath, FileMode.OpenOrCreate))
using (ZipArchive zip = new ZipArchive(fs, ZipArchiveMode.Update))
{
var demoFile = zip.CreateEntry("foo0.txt", CompressionLevel.NoCompression); //NoCompression does not seem to have an impact
using (var streamWriter = new StreamWriter(demoFile.Open()))
{
streamWriter.Write("Bar!");
}
}
Thats creating me a zip file, where the file in it was written in "DEFLATE" Mode not in STORE. How can I fix this. My thought was, my problem would be solved by using the CompressionLevel.NoCompression.
Also writing the file to the filesystem and zipping the directory is not an option, because i want to create a zipfile with potentially hundred of thousands small files. Furthermore just using GZipStream is not an option, because I want to create a directory structure in the .zip file.
I checked the mode with 7-zip:
(screenshot from 7-zip)
If for whatever reason you are required to add contents to a ZIP file with its compression method explicitly set to STORE (no compression), you will need to use some third party library.
The .NET classes in System.IO.Compression use DEFLATE by default. There is no apparent way to change this and use another compression method or algorithm.
Providing CompressionLevel.NoCompression just tells the DEFLATE algorithm to work with the lowest compression rate1. In terms of file size, this will probably give you roughly the same end result, anyway.
Third party libraries supporting the method STORE include:
SharpCompress
(see supported formats)
SharpZipLib
(see compression methods)
DotNetZip
1 which should be... no compression. See DEFLATE's non-compressed blocks
For anyone who happens to see this topic later on, I would highly recommend the ZipStorer class by Jaime Olivares:
https://github.com/jaime-olivares/zipstorer
It's easy to add this code to a C# project (not a DLL), and it's easy to add files using 'store' instead of 'deflate'.
Related
I'm trying to save a large amount of data to a XML and the file ends up with a very large size. I've searched compression but all examples I found first write the file, then read it to compress to another file, ending with both the large and the compressed files, and the closest I got to removing the intermediate step of writing then reading, ended up with a zip containing an extension-less file(which I can open in notepad as a XML).
this is what I have now:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (FileStream outFile = File.Create(#"File.zip"))
{
using (GZipStream Compress = new GZipStream(outFile, CompressionMode.Compress))
{
using (XmlWriter writer = XmlWriter.Create(Compress, settings))
{
//write the XML
}
}
}
How do I make the file inside the zip have the XML extension?
I think this might be a little misunderstanding of fundamentals. From what I know, GZip is a compression system, but not an archiving system. When working with UNIX systems, they tend to be treated as two separate things (whereas ZIP or RAR compression does both). Archiving puts a number of files in one file, and compression makes that file smaller.
Have you ever seen Unix packages that are downloaded as "filename.tar.gz"? That's generally the naming format - they took an archive file (filename.tar) and applied GZip compression to it (filename.tar.gz)
Actually, you're technically kind of causing a bit of confusion by naming your file ".zip" (which is a completely different, more commonly-used format). if you want to follow along with UNIX traditions, just name your file "file.xml.gz". If you want to archive it, use a Tar archiving library. Other libraries such as 7-zip's may have simpler compression systems that will do both for you, for instance if you want this file to be a .zip, easily read by people on Windows computers.
I think you have to write to a temp file first. Take a look at
DotNetPerls
I need to compress a file as 7zip using SharpCompress: http://sharpcompress.codeplex.com
what I have done as follows:
using (var archive = ZipArchive.Create())
{
archive.AddEntry("CompressionTest.pdb", new FileInfo("CompressionTest.pdb"));
using (Stream newStream = File.Create("CompressionTest212.7z"))
{
archive.SaveTo(newStream, SharpCompress.Common.CompressionType.LZMA);
}
}
The compression process is done successfully. However, the compressed file can not be extracted either using 7z (http://www.7-zip.org/download.html) or winrar.
I dont know if somebody also got the same problem and had an idea how to solve it?
Thanks in advance.
I'm the author of SharpCompress (thanks for trying it out by the way) and 7Zip compression isn't supported: http://sharpcompress.codeplex.com/wikipage?title=Supported%20formats
What you wrote is code for creating a standard Zip file with LZMA compression. It's possible my code does not create a proper zip file but it's also possible that the created file can't be read by all programs. The Zip format allows for LZMA compression but not all programs may expect it. PeaZip (based on the 7Zip archiver code) does extract a Zip with LZMA, but WinRAR does not.
If you really need the 7Zip format, I do suggest using something else. Personally, I think the 7Zip format is overly complex and recommend Zip or Tar then just pick your compression of choice.
SharpCompress doesn't support 7zip compression. Only decompression, see: http://sharpcompress.codeplex.com/ ( Supported Format Table )
You can use the native library of 7zip for compression, or use an opensource wrapper around it like: http://sevenzipsharp.codeplex.com/
I have a single file, Setup1.cab, which is split up into Setup1.zip.001 and Setup1.zip.002 that I used 7zip to archive. Once those volumes reach their destination, I'd like to be able to use C# to extract that file from both archives into the same directory where they will reside. Is this something that SharpZipLib is capable of, or should I be using another tool?
Otherwise, is there a way to combine the two using C# (or another tool - I'm open!) into one zip file, THEN extract it using SharpZipLib?
Thanks!
EDIT: 7zip will not be installed on the destination machines. Also, I'm open to using a different method of archiving the original file; I just need it to be in chunks of under 500MB, and the original file is 570MB.
I would take a look at the SevenZipSharp library and actually use 7zip via C# to handle the decompression.
Greetings....
I am writing a backup program in c# 3.5, using hte latest DotNetZip. The basics of the program is to be given a location on a server and the max size of a spanned zip file and go. From there it should traverse all the folder/files from the given location and add them to the archive, keeping the exact structure. It should also compress everything down to a reasonable amount. A given uncompressed collection of folders/files could easily be 10-25gb, with the created spanned files being limited to about 1gb each.
I have everything working (using DotNetZip). My only challenge is there is little to no compession actually happening. I chose to use the "AddDirectory" method for simplicity of code and just generally how well it seemed to fit my project. After reading around I am second guessing that decision.
Given the below code and the large amount of files in an archive, should I compress each file as it is added to the zip? or should the Adddirectory method provide about the same compression?
I have tried every level of compression offered by Ionic.Zlib.CompressionLevel and none seem to help. Should I think about using an outside compression algorithm and stream it into my DotNetZip file?
using (ZipFile zip = new ZipFile())
{
zip.AddDirectory(root.FullName);
if (zipPassword.Length > 0)
zip.Password = zipPassword;
float size = zipGbSize * 1024 * 1024 * 1024;
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
zip.AddProgress += new EventHandler<AddProgressEventArgs>(Zip_AddProgress);
zip.ZipError += new EventHandler<ZipErrorEventArgs>(Zip_ZipError);
zip.Comment = "This zip was created at " + System.DateTime.Now.ToString("G");
zip.MaxOutputSegmentSize = (int)size; //in gig
zip.Name = archiveDir.FullName + #"\Task_" + taskId.ToString() + ".zip";
zip.Save();
}
Thank you for any help!
1.Given the below code and the large amount of files in an archive, should I compress each file as it is added to the zip?
The way DotNetZip works is to compress each file as it is added to the archive. Your app does not need to do compression. DotNetZip does this for you.
or should the Adddirectory method provide about the same compression?
Entries added to a zip file via the AddDirectory() method go through the same code path when the zip archive is written, as entries added via AddFile(). The file data is compressed, then optionally encrypted, then written to the zip file.
an unsolicited tip: you don't need to do:
zip.AddProgress += new EventHandler<AddProgressEventArgs>(Zip_AddProgress);
you can just do:
zip.AddProgress += Zip_AddProgress;
how are you determining that no compression is occurring?
If you are curious about the compression on each entry, you can register a SaveProgress event handler. The SaveProgress event is fired at various times during the writing of an archive, including when saving begins, when DotNetZip begins writing the data for one entry, at various intervals during the writing of one entry, after finishing writing the data for each entry, and after finishing writing all data. These stages and described in the ZipProgressEventType enumeration. When the EventType is Saving_AfterWriteEntry, you can calculate the compression ratio for THAT particular entry.
To verify that compression is not occurring, I'd suggest that you register such a SaveProgress event and look at that compression ratio.
Also, as described above, some file types cannot be compressed. JPG, MPG, MP3, ZIP files, and others are not very compressible.
Finally, doing a backup may be lots easier to do if you just use the DotNetZip command-line tool. If all you want to do is backup a particular directory, you could use the command line tool (zipit.exe) and avoid writing a program. With the zipit.exe tool, if you use the -v option, the tool prints progress reports, and will display the compression for each entry, via the mechanism I described above. Even if you prefer to write your own program, you might consider using zipit.exe to verify that compression is, or is not, occuring when you use DotNetZip.
Im not sure to have understated your question, but the maximum size for any zip file its 4Gb. Maybe you have to create a new ZipFile every time you reach that limit.
Sorry if that doesnt help you.
What sort of data are you compressing? Some sorts of data just doesn't compress very well, for example JPEGs, or ZIP files which are already compressed.
I have a directory that contains several files. I want compress this folder to a zip or tar.gz file. How can I do his work in C#?
You can use DotNetZip Library. It has quite rich and useful features.
EDIT:
string[] MainDirs = Directory.GetDirectories(DirString);
for (int i = 0; i < MainDirs.Length; i++)
{
using (ZipFile zip = new ZipFile())
{
zip.UseUnicodeAsNecessary = true;
zip.AddDirectory(MainDirs[i]);
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
zip.Comment = "This zip was created at " + System.DateTime.Now.ToString("G");
zip.Save(string.Format("test{0}.zip", i));
}
}
Look into using SharpZipLib. It supports both GZip and ZIP compression in C#.
There is an excellent tutorial here outlining what you need to do to zip a directory with SharpZipLib.
use 7zip from commandline in C# --> LZMA SDK supports C#, and there are codesamples in the package
i use the System.IO.Packaging Namespace which was introduced with .NET Framework 3.5. I decided to use that one because it's based on .NET Framework Base classes and no 3rd party code is required which blows up the size of the code..
here's another post on Stackoverflow regarding this Question
And here's the Namespace and ZipPackage declaration / explanation #MSDN
hope that helps
Christian
At my previous job we used #ziplib.
The question is quite old and so are the answers.
Best answer since end of 2012 is: Use .NET 4.5 and the contained System.IO.Compression and System.IO.Compression.ZipArchive namespace classes.
One of many example links you receive if you search in the internet:
http://www.codeproject.com/Articles/381661/Creating-Zip-Files-Easily-in-NET
Since 2014/2015 ff.:
With Roslyn the whole framework library was published as Open Source, so AFAI understand it, you are free to extract the code from the 4.5 classes (as it should be not really system specific) and use it as a library for the earlier .NET frameworks. Maybe this would give some license advantages over using the other classes- but this has to be analyzed by you.
This is a good discussion that discusses the possibility of doing this without any third party libraries. I think you should have a look on it.
Here is a large repository of sample codes that can help you in your work. Good Luck..
GZip is part of Microsoft Framework 2.0 onward.
Its called GZipStream under System.IO.Compression namespace.
To compress a directory with this class, you'd have to create a serializable class (for e.g. Directory) which contains a collection of Files.
The Files class would contain file-name and file-stream to read bytes from file.
Once you do apply GZip on the Directory, it'll read Files one by one and write them to GZipStream.
Check this link: http://www.vwd-cms.com/forum/forums.aspx?topic=18
Another pre-3.5 option is to use the zip utilities from J#. After all, .Net doesn't care what language the code was originally written in ;-).
Articles on how to do this:
ASP-Alliance
MSDN
CodeProject
C-Sharp Corner
You can zip the directory in pure .NET 3.0.
First, you will need a reference to WindowsBase.dll.
This code will open or create a zip file, create a directory inside, and place the file in that directory. If you want to zip a folder, possibly containing sub-directories, you could loop through the files in the directory and call this method for each file. Then, you could depth-first search the sub-directories for files, call the method for each of those and pass in the path to create that hierarchy within the zip file.
public void AddFileToZip(string zipFilename, string fileToAdd, string destDir)
{
using (Package zip = System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate))
{
string destFilename = "." + destDir + "\\" + Path.GetFileName(fileToAdd);
Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
if (zip.PartExists(uri))
{
zip.DeletePart(uri);
}
PackagePart part = zip.CreatePart(uri, "", CompressionOption.Normal);
using (FileStream fileStream = new FileStream(fileToAdd, FileMode.Open, FileAccess.Read))
{
using (Stream dest = part.GetStream())
{
CopyStream(fileStream, dest);
}
}
}
}
destDir could be an empty string, which would place the file directly in the zip.
Sources:
https://weblogs.asp.net/jongalloway/creating-zip-archives-in-net-without-an-external-library-like-sharpziplib
https://weblogs.asp.net/albertpascual/creating-a-folder-inside-the-zip-file-with-system-io-packaging
The most simple solution that I found using System.IO.Compression available from .Net 4.0:
System.IO.Compression.ZipFile.CreateFromDirectory(directoryToArchivePath, archiveDestinationPath);