// UnZip.cs // // ---------------------------------------------------------------------- // Copyright (c) 2006, 2007, 2008 Microsoft Corporation. All rights reserved. // // This example is released under the Microsoft Public License . // See the license.txt file accompanying this release for // full details. // // ---------------------------------------------------------------------- // // This command-line utility unzips a zipfile into the specified directory, // or lists the entries in a zipfile without unzipping. // // compile with: // csc /target:exe /r:Ionic.Zip.dll /out:UnZip.exe UnZip.cs // // created // Wed, 29 Mar 2006 14:36 // using System; using System.Collections.Generic; using Ionic.Zip; namespace Ionic.Zip.Examples { public class UnZip { private static void Usage() { Console.WriteLine("UnZip.exe: extract or list or test the entries in a zip file."); Console.WriteLine(" Depends on Ionic's DotNetZip library. This is version {0} of the utility.", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()); Console.WriteLine("usage:\n" + " unzip [options] [...] \n" + " unzips all files in the archive.\n" + " options:\n" + " - emit extracted content to stdout.\n" + " -o overwrite existing files if necessary.\n" + " -f flatten directory structure when extracting.\n" + " -p specify password for extraction.\n" + " -t test the file for consistency. \n" + " -q operate quietly (no verbose messages). \n" + " -cp extract with the specified numeric codepage. Only do this if you\n" + " know the codepage, and it is neither IBM437 nor UTF-8. If the \n" + " codepage you specify here is different than the codepage of \n" + " the cmd.exe, then the verbose messages will look odd, but the \n" + " files will be extracted properly.\n" + " -d unpack to the specified directory. If none provided, it will\n" + " unzip to the current directory.\n" + " unzip only the specified filename.\n\n" + " unzip -l \n" + " lists the entries in the zip archive.\n" + " unzip -i \n" + " displays full information about all the entries in the zip archive.\n" + " unzip -t [-p ] [-cp ]\n" + " tests the zip archive.\n" + " unzip -r \n" + " repairs the zip archive - rewriting the directory.\n" + " unzip -?\n" + " displays this message.\n" ); Environment.Exit(1); } enum ActionDesired { Extract, List, Info, Test, Repair } public static void Main(String[] args) { int startArgs = 0; int i; int codePage = 0; string zipfile = null; string targdir = null; string password = null; List entriesToExtract = new List(); bool extractToConsole = false; ActionDesired action = ActionDesired.Extract; ExtractExistingFileAction behaviorForExistingFile = ExtractExistingFileAction.DoNotOverwrite; bool wantQuiet = false; bool wantFlatten = false; System.IO.Stream bitbucket = System.IO.Stream.Null; System.IO.Stream outstream = null; // because the comments and filenames on zip entries may be UTF-8 //System.Console.OutputEncoding = new System.Text.UTF8Encoding(); if (args.Length == 0) Usage(); if (args[0] == "-") { extractToConsole = true; outstream = Console.OpenStandardOutput(); startArgs = 1; } for (i = startArgs; i < args.Length; i++) { switch (args[i]) { case "-cp": i++; if (args.Length <= i) Usage(); if (codePage != 0) Usage(); System.Int32.TryParse(args[i], out codePage); break; case "-d": i++; if (args.Length <= i) Usage(); if (targdir != null) Usage(); if (extractToConsole) Usage(); if (action != ActionDesired.Extract) Usage(); targdir = args[i]; break; case "-f": wantFlatten = true; if (action != ActionDesired.Extract) Usage(); break; case "-i": if (password != null) Usage(); if (targdir != null) Usage(); if (wantQuiet) Usage(); if (entriesToExtract.Count > 0) Usage(); action = ActionDesired.Info; break; case "-l": if (password != null) Usage(); if (targdir != null) Usage(); if (wantQuiet) Usage(); if (entriesToExtract.Count > 0) Usage(); if (behaviorForExistingFile == ExtractExistingFileAction.OverwriteSilently) Usage(); action = ActionDesired.List; break; case "-o": behaviorForExistingFile = ExtractExistingFileAction.OverwriteSilently; if (action != ActionDesired.Extract) Usage(); break; case "-r": if (wantFlatten == true) Usage(); if (targdir != null) Usage(); if (action == ActionDesired.Test) Usage(); action = ActionDesired.Repair; break; case "-p": i++; if (args.Length <= i) Usage(); if (password != null) Usage(); password = args[i]; break; case "-q": if (action == ActionDesired.List) Usage(); wantQuiet = true; break; case "-t": action = ActionDesired.Test; if (targdir != null) Usage(); //if (wantQuiet) Usage(); if (entriesToExtract.Count > 0) Usage(); break; case "-?": Usage(); break; default: // positional args if (zipfile == null) zipfile = args[i]; else if (action != ActionDesired.Extract) Usage(); else entriesToExtract.Add(args[i]); break; } } if (zipfile == null) { Console.WriteLine("unzip: No zipfile specified.\n"); Usage(); } if (!System.IO.File.Exists(zipfile)) { Console.WriteLine("unzip: That zip file does not exist!\n"); Usage(); } if (targdir == null) targdir = "."; try { if (action == ActionDesired.Repair) { ZipFile.FixZipDirectory(zipfile); } else { var options = new ReadOptions { Encoding = (codePage != 0) ? System.Text.Encoding.GetEncoding(codePage) : null }; using (ZipFile zip = ZipFile.Read(zipfile, options)) { if (entriesToExtract.Count > 0) { // extract specified entries foreach (var entryToExtract in entriesToExtract) { // find the entry ZipEntry e= zip[entryToExtract]; if (e == null) { System.Console.WriteLine(" entry ({0}) does not exist in the zip archive.", entryToExtract); } else { if (wantFlatten) e.FileName = System.IO.Path.GetFileName(e.FileName); if (password == null) { if (e.UsesEncryption) System.Console.WriteLine(" That entry ({0}) requires a password to extract.", entryToExtract); else if (extractToConsole) e.Extract(outstream); else e.Extract(targdir, behaviorForExistingFile); } else { if (extractToConsole) e.ExtractWithPassword(outstream, password); else e.ExtractWithPassword(targdir, behaviorForExistingFile, password); } } } } else if (action == ActionDesired.Info) { System.Console.WriteLine("{0}", zip.Info); } else { // extract all, or list, or test // The logic here does almost the same thing as the ExtractAll() method // on the ZipFile class. But in this case we *could* have control over // it, for example only extract files of a certain type, or whose names // matched a certain pattern, or whose lastmodified times fit a certain // condition, or use a different password for each entry, etc. We can // also display status for each entry, as here. Int64 totalUncompressedSize = 0; bool header = true; foreach (ZipEntry e in zip.EntriesSorted) { if (!wantQuiet) { 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,10} {3,5} {4,10} {5,3} {6,8} {0}", "Filename", "Modified", "Size", "Ratio", "Packed", "pw?", "CRC"); System.Console.WriteLine(new System.String('-', 80)); header = false; } totalUncompressedSize += e.UncompressedSize; System.Console.WriteLine("{1,-22} {2,10} {3,5:F0}% {4,10} {5,3} {6:X8} {0}", e.FileName, e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), e.UncompressedSize, e.CompressionRatio, e.CompressedSize, (e.UsesEncryption) ? "Y" : "N", e.Crc); if ((e.Comment != null) && (e.Comment != "")) System.Console.WriteLine(" Comment: {0}", e.Comment); } if (action == ActionDesired.Extract) { if (e.UsesEncryption) { if (password == null) System.Console.WriteLine("unzip: {0}: Cannot extract this entry without a password.", e.FileName); else { if (wantFlatten) e.FileName = System.IO.Path.GetFileName(e.FileName); if (extractToConsole) e.ExtractWithPassword(outstream, password); else e.ExtractWithPassword(targdir, behaviorForExistingFile, password); } } else { if (wantFlatten) e.FileName = System.IO.Path.GetFileName(e.FileName); if (extractToConsole) e.Extract(outstream); else e.Extract(targdir, behaviorForExistingFile); } } else if (action == ActionDesired.Test) { e.ExtractWithPassword(bitbucket, password); } } // foreach if (!wantQuiet) { System.Console.WriteLine(new System.String('-', 80)); System.Console.WriteLine("{1,-22} {2,10} {3,5} {4,10} {5,3} {6,8} {0}", zip.Entries.Count.ToString() + " files", "", totalUncompressedSize, "", "", "", ""); } } // else (extract all) } // end using(), the underlying file is closed. } } catch (System.Exception ex1) { System.Console.Error.WriteLine("exception: " + ex1); } Console.WriteLine(); } } }