123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184 |
- // ZipFile.AddUpdate.cs
- // ------------------------------------------------------------------
- //
- // Copyright (c) 2009-2011 Dino Chiesa.
- // All rights reserved.
- //
- // This code module is part of DotNetZip, a zipfile class library.
- //
- // ------------------------------------------------------------------
- //
- // This code is licensed under the Microsoft Public License.
- // See the file License.txt for the license details.
- // More info on: http://dotnetzip.codeplex.com
- //
- // ------------------------------------------------------------------
- //
- // last saved (in emacs):
- // Time-stamp: <2011-November-01 13:56:58>
- //
- // ------------------------------------------------------------------
- //
- // This module defines the methods for Adding and Updating entries in
- // the ZipFile.
- //
- // ------------------------------------------------------------------
- //
- using System;
- using System.IO;
- using System.Collections.Generic;
- namespace Ionic.Zip
- {
- public partial class ZipFile
- {
- /// <summary>
- /// Adds an item, either a file or a directory, to a zip file archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This method is handy if you are adding things to zip archive and don't
- /// want to bother distinguishing between directories or files. Any files are
- /// added as single entries. A directory added through this method is added
- /// recursively: all files and subdirectories contained within the directory
- /// are added to the <c>ZipFile</c>.
- /// </para>
- ///
- /// <para>
- /// The name of the item may be a relative path or a fully-qualified
- /// path. Remember, the items contained in <c>ZipFile</c> instance get written
- /// to the disk only when you call <see cref="ZipFile.Save()"/> or a similar
- /// save method.
- /// </para>
- ///
- /// <para>
- /// The directory name used for the file within the archive is the same
- /// as the directory name (potentially a relative path) specified in the
- /// <paramref name="fileOrDirectoryName"/>.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/>
- ///
- /// <overloads>This method has two overloads.</overloads>
- /// <param name="fileOrDirectoryName">
- /// the name of the file or directory to add.</param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- public ZipEntry AddItem(string fileOrDirectoryName)
- {
- return AddItem(fileOrDirectoryName, null);
- }
- /// <summary>
- /// Adds an item, either a file or a directory, to a zip file archive,
- /// explicitly specifying the directory path to be used in the archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// If adding a directory, the add is recursive on all files and
- /// subdirectories contained within it.
- /// </para>
- /// <para>
- /// The name of the item may be a relative path or a fully-qualified path.
- /// The item added by this call to the <c>ZipFile</c> is not read from the
- /// disk nor written to the zip file archive until the application calls
- /// Save() on the <c>ZipFile</c>.
- /// </para>
- ///
- /// <para>
- /// This version of the method allows the caller to explicitly specify the
- /// directory path to be used in the archive, which would override the
- /// "natural" path of the filesystem file.
- /// </para>
- ///
- /// <para>
- /// Encryption will be used on the file data if the <c>Password</c> has
- /// been set on the <c>ZipFile</c> object, prior to calling this method.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <exception cref="System.IO.FileNotFoundException">
- /// Thrown if the file or directory passed in does not exist.
- /// </exception>
- ///
- /// <param name="fileOrDirectoryName">the name of the file or directory to add.
- /// </param>
- ///
- /// <param name="directoryPathInArchive">
- /// The name of the directory path to use within the zip archive. This path
- /// need not refer to an extant directory in the current filesystem. If the
- /// files within the zip are later extracted, this is the path used for the
- /// extracted file. Passing <c>null</c> (<c>Nothing</c> in VB) will use the
- /// path on the fileOrDirectoryName. Passing the empty string ("") will
- /// insert the item at the root path within the archive.
- /// </param>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string, string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string, string)"/>
- ///
- /// <example>
- /// This example shows how to zip up a set of files into a flat hierarchy,
- /// regardless of where in the filesystem the files originated. The resulting
- /// zip archive will contain a toplevel directory named "flat", which itself
- /// will contain files Readme.txt, MyProposal.docx, and Image1.jpg. A
- /// subdirectory under "flat" called SupportFiles will contain all the files
- /// in the "c:\SupportFiles" directory on disk.
- ///
- /// <code>
- /// String[] itemnames= {
- /// "c:\\fixedContent\\Readme.txt",
- /// "MyProposal.docx",
- /// "c:\\SupportFiles", // a directory
- /// "images\\Image1.jpg"
- /// };
- ///
- /// try
- /// {
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// for (int i = 1; i < itemnames.Length; i++)
- /// {
- /// // will add Files or Dirs, recurses and flattens subdirectories
- /// zip.AddItem(itemnames[i],"flat");
- /// }
- /// zip.Save(ZipToCreate);
- /// }
- /// }
- /// catch (System.Exception ex1)
- /// {
- /// System.Console.Error.WriteLine("exception: {0}", ex1);
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Dim itemnames As String() = _
- /// New String() { "c:\fixedContent\Readme.txt", _
- /// "MyProposal.docx", _
- /// "SupportFiles", _
- /// "images\Image1.jpg" }
- /// Try
- /// Using zip As New ZipFile
- /// Dim i As Integer
- /// For i = 1 To itemnames.Length - 1
- /// ' will add Files or Dirs, recursing and flattening subdirectories.
- /// zip.AddItem(itemnames(i), "flat")
- /// Next i
- /// zip.Save(ZipToCreate)
- /// End Using
- /// Catch ex1 As Exception
- /// Console.Error.WriteLine("exception: {0}", ex1.ToString())
- /// End Try
- /// </code>
- /// </example>
- /// <returns>The <c>ZipEntry</c> added.</returns>
- public ZipEntry AddItem(String fileOrDirectoryName, String directoryPathInArchive)
- {
- if (File.Exists(fileOrDirectoryName))
- return AddFile(fileOrDirectoryName, directoryPathInArchive);
- if (Directory.Exists(fileOrDirectoryName))
- return AddDirectory(fileOrDirectoryName, directoryPathInArchive);
- throw new FileNotFoundException(String.Format("That file or directory ({0}) does not exist!",
- fileOrDirectoryName));
- }
- /// <summary>
- /// Adds a File to a Zip file archive.
- /// </summary>
- /// <remarks>
- ///
- /// <para>
- /// This call collects metadata for the named file in the filesystem,
- /// including the file attributes and the timestamp, and inserts that metadata
- /// into the resulting ZipEntry. Only when the application calls Save() on
- /// the <c>ZipFile</c>, does DotNetZip read the file from the filesystem and
- /// then write the content to the zip file archive.
- /// </para>
- ///
- /// <para>
- /// This method will throw an exception if an entry with the same name already
- /// exists in the <c>ZipFile</c>.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// <para>
- /// In this example, three files are added to a Zip archive. The ReadMe.txt
- /// file will be placed in the root of the archive. The .png file will be
- /// placed in a folder within the zip called photos\personal. The pdf file
- /// will be included into a folder within the zip called Desktop.
- /// </para>
- /// <code>
- /// try
- /// {
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// zip.AddFile("c:\\photos\\personal\\7440-N49th.png");
- /// zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf");
- /// zip.AddFile("ReadMe.txt");
- ///
- /// zip.Save("Package.zip");
- /// }
- /// }
- /// catch (System.Exception ex1)
- /// {
- /// System.Console.Error.WriteLine("exception: " + ex1);
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Try
- /// Using zip As ZipFile = New ZipFile
- /// zip.AddFile("c:\photos\personal\7440-N49th.png")
- /// zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf")
- /// zip.AddFile("ReadMe.txt")
- /// zip.Save("Package.zip")
- /// End Using
- /// Catch ex1 As Exception
- /// Console.Error.WriteLine("exception: {0}", ex1.ToString)
- /// End Try
- /// </code>
- /// </example>
- ///
- /// <overloads>This method has two overloads.</overloads>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/>
- ///
- /// <param name="fileName">
- /// The name of the file to add. It should refer to a file in the filesystem.
- /// The name of the file may be a relative path or a fully-qualified path.
- /// </param>
- /// <returns>The <c>ZipEntry</c> corresponding to the File added.</returns>
- public ZipEntry AddFile(string fileName)
- {
- return AddFile(fileName, null);
- }
- /// <summary>
- /// Adds a File to a Zip file archive, potentially overriding the path to be
- /// used within the zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// The file added by this call to the <c>ZipFile</c> is not written to the
- /// zip file archive until the application calls Save() on the <c>ZipFile</c>.
- /// </para>
- ///
- /// <para>
- /// This method will throw an exception if an entry with the same name already
- /// exists in the <c>ZipFile</c>.
- /// </para>
- ///
- /// <para>
- /// This version of the method allows the caller to explicitly specify the
- /// directory path to be used in the archive.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// <para>
- /// In this example, three files are added to a Zip archive. The ReadMe.txt
- /// file will be placed in the root of the archive. The .png file will be
- /// placed in a folder within the zip called images. The pdf file will be
- /// included into a folder within the zip called files\docs, and will be
- /// encrypted with the given password.
- /// </para>
- /// <code>
- /// try
- /// {
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// // the following entry will be inserted at the root in the archive.
- /// zip.AddFile("c:\\datafiles\\ReadMe.txt", "");
- /// // this image file will be inserted into the "images" directory in the archive.
- /// zip.AddFile("c:\\photos\\personal\\7440-N49th.png", "images");
- /// // the following will result in a password-protected file called
- /// // files\\docs\\2008-Regional-Sales-Report.pdf in the archive.
- /// zip.Password = "EncryptMe!";
- /// zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf", "files\\docs");
- /// zip.Save("Archive.zip");
- /// }
- /// }
- /// catch (System.Exception ex1)
- /// {
- /// System.Console.Error.WriteLine("exception: {0}", ex1);
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Try
- /// Using zip As ZipFile = New ZipFile
- /// ' the following entry will be inserted at the root in the archive.
- /// zip.AddFile("c:\datafiles\ReadMe.txt", "")
- /// ' this image file will be inserted into the "images" directory in the archive.
- /// zip.AddFile("c:\photos\personal\7440-N49th.png", "images")
- /// ' the following will result in a password-protected file called
- /// ' files\\docs\\2008-Regional-Sales-Report.pdf in the archive.
- /// zip.Password = "EncryptMe!"
- /// zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf", "files\documents")
- /// zip.Save("Archive.zip")
- /// End Using
- /// Catch ex1 As Exception
- /// Console.Error.WriteLine("exception: {0}", ex1)
- /// End Try
- /// </code>
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string,string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string,string)"/>
- ///
- /// <param name="fileName">
- /// The name of the file to add. The name of the file may be a relative path
- /// or a fully-qualified path.
- /// </param>
- ///
- /// <param name="directoryPathInArchive">
- /// Specifies a directory path to use to override any path in the fileName.
- /// This path may, or may not, correspond to a real directory in the current
- /// filesystem. If the files within the zip are later extracted, this is the
- /// path used for the extracted file. Passing <c>null</c> (<c>Nothing</c> in
- /// VB) will use the path on the fileName, if any. Passing the empty string
- /// ("") will insert the item at the root path within the archive.
- /// </param>
- ///
- /// <returns>The <c>ZipEntry</c> corresponding to the file added.</returns>
- public ZipEntry AddFile(string fileName, String directoryPathInArchive)
- {
- string nameInArchive = ZipEntry.NameInArchive(fileName, directoryPathInArchive);
- ZipEntry ze = ZipEntry.CreateFromFile(fileName, nameInArchive);
- if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", fileName);
- return _InternalAddEntry(ze);
- }
- /// <summary>
- /// This method removes a collection of entries from the <c>ZipFile</c>.
- /// </summary>
- ///
- /// <param name="entriesToRemove">
- /// A collection of ZipEntry instances from this zip file to be removed. For
- /// example, you can pass in an array of ZipEntry instances; or you can call
- /// SelectEntries(), and then add or remove entries from that
- /// ICollection<ZipEntry> (ICollection(Of ZipEntry) in VB), and pass
- /// that ICollection to this method.
- /// </param>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.SelectEntries(String)" />
- /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(String)" />
- public void RemoveEntries(System.Collections.Generic.ICollection<ZipEntry> entriesToRemove)
- {
- if (entriesToRemove == null)
- throw new ArgumentNullException("entriesToRemove");
- foreach (ZipEntry e in entriesToRemove)
- {
- this.RemoveEntry(e);
- }
- }
- /// <summary>
- /// This method removes a collection of entries from the <c>ZipFile</c>, by name.
- /// </summary>
- ///
- /// <param name="entriesToRemove">
- /// A collection of strings that refer to names of entries to be removed
- /// from the <c>ZipFile</c>. For example, you can pass in an array or a
- /// List of Strings that provide the names of entries to be removed.
- /// </param>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.SelectEntries(String)" />
- /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(String)" />
- public void RemoveEntries(System.Collections.Generic.ICollection<String> entriesToRemove)
- {
- if (entriesToRemove == null)
- throw new ArgumentNullException("entriesToRemove");
- foreach (String e in entriesToRemove)
- {
- this.RemoveEntry(e);
- }
- }
- /// <summary>
- /// This method adds a set of files to the <c>ZipFile</c>.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// Use this method to add a set of files to the zip archive, in one call.
- /// For example, a list of files received from
- /// <c>System.IO.Directory.GetFiles()</c> can be added to a zip archive in one
- /// call.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to each
- /// ZipEntry added.
- /// </para>
- /// </remarks>
- ///
- /// <param name="fileNames">
- /// The collection of names of the files to add. Each string should refer to a
- /// file in the filesystem. The name of the file may be a relative path or a
- /// fully-qualified path.
- /// </param>
- ///
- /// <example>
- /// This example shows how to create a zip file, and add a few files into it.
- /// <code>
- /// String ZipFileToCreate = "archive1.zip";
- /// String DirectoryToZip = "c:\\reports";
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// // Store all files found in the top level directory, into the zip archive.
- /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
- /// zip.AddFiles(filenames);
- /// zip.Save(ZipFileToCreate);
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Dim ZipFileToCreate As String = "archive1.zip"
- /// Dim DirectoryToZip As String = "c:\reports"
- /// Using zip As ZipFile = New ZipFile
- /// ' Store all files found in the top level directory, into the zip archive.
- /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
- /// zip.AddFiles(filenames)
- /// zip.Save(ZipFileToCreate)
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" />
- public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames)
- {
- this.AddFiles(fileNames, null);
- }
- /// <summary>
- /// Adds or updates a set of files in the <c>ZipFile</c>.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// Any files that already exist in the archive are updated. Any files that
- /// don't yet exist in the archive are added.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to each
- /// ZipEntry added.
- /// </para>
- /// </remarks>
- ///
- /// <param name="fileNames">
- /// The collection of names of the files to update. Each string should refer to a file in
- /// the filesystem. The name of the file may be a relative path or a fully-qualified path.
- /// </param>
- ///
- public void UpdateFiles(System.Collections.Generic.IEnumerable<String> fileNames)
- {
- this.UpdateFiles(fileNames, null);
- }
- /// <summary>
- /// Adds a set of files to the <c>ZipFile</c>, using the
- /// specified directory path in the archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// Any directory structure that may be present in the
- /// filenames contained in the list is "flattened" in the
- /// archive. Each file in the list is added to the archive in
- /// the specified top-level directory.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see
- /// cref="Encryption"/>, <see cref="Password"/>, <see
- /// cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see
- /// cref="ExtractExistingFile"/>, <see
- /// cref="ZipErrorAction"/>, and <see
- /// cref="CompressionLevel"/>, their respective values at the
- /// time of this call will be applied to each ZipEntry added.
- /// </para>
- /// </remarks>
- ///
- /// <param name="fileNames">
- /// The names of the files to add. Each string should refer to
- /// a file in the filesystem. The name of the file may be a
- /// relative path or a fully-qualified path.
- /// </param>
- ///
- /// <param name="directoryPathInArchive">
- /// Specifies a directory path to use to override any path in the file name.
- /// Th is path may, or may not, correspond to a real directory in the current
- /// filesystem. If the files within the zip are later extracted, this is the
- /// path used for the extracted file. Passing <c>null</c> (<c>Nothing</c> in
- /// VB) will use the path on each of the <c>fileNames</c>, if any. Passing
- /// the empty string ("") will insert the item at the root path within the
- /// archive.
- /// </param>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" />
- public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames, String directoryPathInArchive)
- {
- AddFiles(fileNames, false, directoryPathInArchive);
- }
- /// <summary>
- /// Adds a set of files to the <c>ZipFile</c>, using the specified directory
- /// path in the archive, and preserving the full directory structure in the
- /// filenames.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// Think of the <paramref name="directoryPathInArchive"/> as a "root" or
- /// base directory used in the archive for the files that get added. when
- /// <paramref name="preserveDirHierarchy"/> is true, the hierarchy of files
- /// found in the filesystem will be placed, with the hierarchy intact,
- /// starting at that root in the archive. When <c>preserveDirHierarchy</c>
- /// is false, the path hierarchy of files is flattned, and the flattened
- /// set of files gets placed in the root within the archive as specified in
- /// <c>directoryPathInArchive</c>.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to each
- /// ZipEntry added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <param name="fileNames">
- /// The names of the files to add. Each string should refer to a file in the
- /// filesystem. The name of the file may be a relative path or a
- /// fully-qualified path.
- /// </param>
- ///
- /// <param name="directoryPathInArchive">
- /// Specifies a directory path to use as a prefix for each entry name.
- /// This path may, or may not, correspond to a real directory in the current
- /// filesystem. If the files within the zip are later extracted, this is the
- /// path used for the extracted file. Passing <c>null</c> (<c>Nothing</c> in
- /// VB) will use the path on each of the <c>fileNames</c>, if any. Passing
- /// the empty string ("") will insert the item at the root path within the
- /// archive.
- /// </param>
- ///
- /// <param name="preserveDirHierarchy">
- /// whether the entries in the zip archive will reflect the directory
- /// hierarchy that is present in the various filenames. For example, if
- /// <paramref name="fileNames"/> includes two paths,
- /// \Animalia\Chordata\Mammalia\Info.txt and
- /// \Plantae\Magnoliophyta\Dicotyledon\Info.txt, then calling this method
- /// with <paramref name="preserveDirHierarchy"/> = <c>false</c> will
- /// result in an exception because of a duplicate entry name, while
- /// calling this method with <paramref name="preserveDirHierarchy"/> =
- /// <c>true</c> will result in the full direcory paths being included in
- /// the entries added to the ZipFile.
- /// </param>
- /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" />
- public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames,
- bool preserveDirHierarchy,
- String directoryPathInArchive)
- {
- if (fileNames == null)
- throw new ArgumentNullException("fileNames");
- _addOperationCanceled = false;
- OnAddStarted();
- if (preserveDirHierarchy)
- {
- foreach (var f in fileNames)
- {
- if (_addOperationCanceled) break;
- if (directoryPathInArchive != null)
- {
- //string s = SharedUtilities.NormalizePath(Path.Combine(directoryPathInArchive, Path.GetDirectoryName(f)));
- string s = Path.GetFullPath(Path.Combine(directoryPathInArchive, Path.GetDirectoryName(f)));
- this.AddFile(f, s);
- }
- else
- this.AddFile(f, null);
- }
- }
- else
- {
- foreach (var f in fileNames)
- {
- if (_addOperationCanceled) break;
- this.AddFile(f, directoryPathInArchive);
- }
- }
- if (!_addOperationCanceled)
- OnAddCompleted();
- }
- /// <summary>
- /// Adds or updates a set of files to the <c>ZipFile</c>, using the specified
- /// directory path in the archive.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// Any files that already exist in the archive are updated. Any files that
- /// don't yet exist in the archive are added.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to each
- /// ZipEntry added.
- /// </para>
- /// </remarks>
- ///
- /// <param name="fileNames">
- /// The names of the files to add or update. Each string should refer to a
- /// file in the filesystem. The name of the file may be a relative path or a
- /// fully-qualified path.
- /// </param>
- ///
- /// <param name="directoryPathInArchive">
- /// Specifies a directory path to use to override any path in the file name.
- /// This path may, or may not, correspond to a real directory in the current
- /// filesystem. If the files within the zip are later extracted, this is the
- /// path used for the extracted file. Passing <c>null</c> (<c>Nothing</c> in
- /// VB) will use the path on each of the <c>fileNames</c>, if any. Passing
- /// the empty string ("") will insert the item at the root path within the
- /// archive.
- /// </param>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" />
- public void UpdateFiles(System.Collections.Generic.IEnumerable<String> fileNames, String directoryPathInArchive)
- {
- if (fileNames == null)
- throw new ArgumentNullException("fileNames");
- OnAddStarted();
- foreach (var f in fileNames)
- this.UpdateFile(f, directoryPathInArchive);
- OnAddCompleted();
- }
- /// <summary>
- /// Adds or Updates a File in a Zip file archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This method adds a file to a zip archive, or, if the file already exists
- /// in the zip archive, this method Updates the content of that given filename
- /// in the zip archive. The <c>UpdateFile</c> method might more accurately be
- /// called "AddOrUpdateFile".
- /// </para>
- ///
- /// <para>
- /// Upon success, there is no way for the application to learn whether the file
- /// was added versus updated.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- /// </remarks>
- ///
- /// <example>
- ///
- /// This example shows how to Update an existing entry in a zipfile. The first
- /// call to UpdateFile adds the file to the newly-created zip archive. The
- /// second call to UpdateFile updates the content for that file in the zip
- /// archive.
- ///
- /// <code>
- /// using (ZipFile zip1 = new ZipFile())
- /// {
- /// // UpdateFile might more accurately be called "AddOrUpdateFile"
- /// zip1.UpdateFile("MyDocuments\\Readme.txt");
- /// zip1.UpdateFile("CustomerList.csv");
- /// zip1.Comment = "This zip archive has been created.";
- /// zip1.Save("Content.zip");
- /// }
- ///
- /// using (ZipFile zip2 = ZipFile.Read("Content.zip"))
- /// {
- /// zip2.UpdateFile("Updates\\Readme.txt");
- /// zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed.";
- /// zip2.Save();
- /// }
- ///
- /// </code>
- /// <code lang="VB">
- /// Using zip1 As New ZipFile
- /// ' UpdateFile might more accurately be called "AddOrUpdateFile"
- /// zip1.UpdateFile("MyDocuments\Readme.txt")
- /// zip1.UpdateFile("CustomerList.csv")
- /// zip1.Comment = "This zip archive has been created."
- /// zip1.Save("Content.zip")
- /// End Using
- ///
- /// Using zip2 As ZipFile = ZipFile.Read("Content.zip")
- /// zip2.UpdateFile("Updates\Readme.txt")
- /// zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed."
- /// zip2.Save
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/>
- ///
- /// <param name="fileName">
- /// The name of the file to add or update. It should refer to a file in the
- /// filesystem. The name of the file may be a relative path or a
- /// fully-qualified path.
- /// </param>
- ///
- /// <returns>
- /// The <c>ZipEntry</c> corresponding to the File that was added or updated.
- /// </returns>
- public ZipEntry UpdateFile(string fileName)
- {
- return UpdateFile(fileName, null);
- }
- /// <summary>
- /// Adds or Updates a File in a Zip file archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This method adds a file to a zip archive, or, if the file already exists
- /// in the zip archive, this method Updates the content of that given filename
- /// in the zip archive.
- /// </para>
- ///
- /// <para>
- /// This version of the method allows the caller to explicitly specify the
- /// directory path to be used in the archive. The entry to be added or
- /// updated is found by using the specified directory path, combined with the
- /// basename of the specified filename.
- /// </para>
- ///
- /// <para>
- /// Upon success, there is no way for the application to learn if the file was
- /// added versus updated.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string,string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string,string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string,string)"/>
- ///
- /// <param name="fileName">
- /// The name of the file to add or update. It should refer to a file in the
- /// filesystem. The name of the file may be a relative path or a
- /// fully-qualified path.
- /// </param>
- ///
- /// <param name="directoryPathInArchive">
- /// Specifies a directory path to use to override any path in the
- /// <c>fileName</c>. This path may, or may not, correspond to a real
- /// directory in the current filesystem. If the files within the zip are
- /// later extracted, this is the path used for the extracted file. Passing
- /// <c>null</c> (<c>Nothing</c> in VB) will use the path on the
- /// <c>fileName</c>, if any. Passing the empty string ("") will insert the
- /// item at the root path within the archive.
- /// </param>
- ///
- /// <returns>
- /// The <c>ZipEntry</c> corresponding to the File that was added or updated.
- /// </returns>
- public ZipEntry UpdateFile(string fileName, String directoryPathInArchive)
- {
- // ideally this would all be transactional!
- var key = ZipEntry.NameInArchive(fileName, directoryPathInArchive);
- if (this[key] != null)
- this.RemoveEntry(key);
- return this.AddFile(fileName, directoryPathInArchive);
- }
- /// <summary>
- /// Add or update a directory in a zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// If the specified directory does not exist in the archive, then this method
- /// is equivalent to calling <c>AddDirectory()</c>. If the specified
- /// directory already exists in the archive, then this method updates any
- /// existing entries, and adds any new entries. Any entries that are in the
- /// zip archive but not in the specified directory, are left alone. In other
- /// words, the contents of the zip file will be a union of the previous
- /// contents and the new files.
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/>
- ///
- /// <param name="directoryName">
- /// The path to the directory to be added to the zip archive, or updated in
- /// the zip archive.
- /// </param>
- ///
- /// <returns>
- /// The <c>ZipEntry</c> corresponding to the Directory that was added or updated.
- /// </returns>
- public ZipEntry UpdateDirectory(string directoryName)
- {
- return UpdateDirectory(directoryName, null);
- }
- /// <summary>
- /// Add or update a directory in the zip archive at the specified root
- /// directory in the archive.
- /// </summary>
- ///
- /// <remarks>
- /// If the specified directory does not exist in the archive, then this method
- /// is equivalent to calling <c>AddDirectory()</c>. If the specified
- /// directory already exists in the archive, then this method updates any
- /// existing entries, and adds any new entries. Any entries that are in the
- /// zip archive but not in the specified directory, are left alone. In other
- /// words, the contents of the zip file will be a union of the previous
- /// contents and the new files.
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string,string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string,string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string,string)"/>
- ///
- /// <param name="directoryName">
- /// The path to the directory to be added to the zip archive, or updated
- /// in the zip archive.
- /// </param>
- ///
- /// <param name="directoryPathInArchive">
- /// Specifies a directory path to use to override any path in the
- /// <c>directoryName</c>. This path may, or may not, correspond to a real
- /// directory in the current filesystem. If the files within the zip are
- /// later extracted, this is the path used for the extracted file. Passing
- /// <c>null</c> (<c>Nothing</c> in VB) will use the path on the
- /// <c>directoryName</c>, if any. Passing the empty string ("") will insert
- /// the item at the root path within the archive.
- /// </param>
- ///
- /// <returns>
- /// The <c>ZipEntry</c> corresponding to the Directory that was added or updated.
- /// </returns>
- public ZipEntry UpdateDirectory(string directoryName, String directoryPathInArchive)
- {
- return this.AddOrUpdateDirectoryImpl(directoryName, directoryPathInArchive, AddOrUpdateAction.AddOrUpdate);
- }
- /// <summary>
- /// Add or update a file or directory in the zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This is useful when the application is not sure or does not care if the
- /// item to be added is a file or directory, and does not know or does not
- /// care if the item already exists in the <c>ZipFile</c>. Calling this method
- /// is equivalent to calling <c>RemoveEntry()</c> if an entry by the same name
- /// already exists, followed calling by <c>AddItem()</c>.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/>
- ///
- /// <param name="itemName">
- /// the path to the file or directory to be added or updated.
- /// </param>
- public void UpdateItem(string itemName)
- {
- UpdateItem(itemName, null);
- }
- /// <summary>
- /// Add or update a file or directory.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This method is useful when the application is not sure or does not care if
- /// the item to be added is a file or directory, and does not know or does not
- /// care if the item already exists in the <c>ZipFile</c>. Calling this method
- /// is equivalent to calling <c>RemoveEntry()</c>, if an entry by that name
- /// exists, and then calling <c>AddItem()</c>.
- /// </para>
- ///
- /// <para>
- /// This version of the method allows the caller to explicitly specify the
- /// directory path to be used for the item being added to the archive. The
- /// entry or entries that are added or updated will use the specified
- /// <c>DirectoryPathInArchive</c>. Extracting the entry from the archive will
- /// result in a file stored in that directory path.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string, string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string, string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string, string)"/>
- ///
- /// <param name="itemName">
- /// The path for the File or Directory to be added or updated.
- /// </param>
- /// <param name="directoryPathInArchive">
- /// Specifies a directory path to use to override any path in the
- /// <c>itemName</c>. This path may, or may not, correspond to a real
- /// directory in the current filesystem. If the files within the zip are
- /// later extracted, this is the path used for the extracted file. Passing
- /// <c>null</c> (<c>Nothing</c> in VB) will use the path on the
- /// <c>itemName</c>, if any. Passing the empty string ("") will insert the
- /// item at the root path within the archive.
- /// </param>
- public void UpdateItem(string itemName, string directoryPathInArchive)
- {
- if (File.Exists(itemName))
- UpdateFile(itemName, directoryPathInArchive);
- else if (Directory.Exists(itemName))
- UpdateDirectory(itemName, directoryPathInArchive);
- else
- throw new FileNotFoundException(String.Format("That file or directory ({0}) does not exist!", itemName));
- }
- /// <summary>
- /// Adds a named entry into the zip archive, taking content for the entry
- /// from a string.
- /// </summary>
- ///
- /// <remarks>
- /// Calling this method creates an entry using the given fileName and
- /// directory path within the archive. There is no need for a file by the
- /// given name to exist in the filesystem; the name is used within the zip
- /// archive only. The content for the entry is encoded using the default text
- /// encoding for the machine, or on Silverlight, using UTF-8.
- /// </remarks>
- ///
- /// <param name="content">
- /// The content of the file, should it be extracted from the zip.
- /// </param>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use for the entry within the archive.
- /// </param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- ///
- /// <example>
- ///
- /// This example shows how to add an entry to the zipfile, using a string as
- /// content for that entry.
- ///
- /// <code lang="C#">
- /// string Content = "This string will be the content of the Readme.txt file in the zip archive.";
- /// using (ZipFile zip1 = new ZipFile())
- /// {
- /// zip1.AddFile("MyDocuments\\Resume.doc", "files");
- /// zip1.AddEntry("Readme.txt", Content);
- /// zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G");
- /// zip1.Save("Content.zip");
- /// }
- ///
- /// </code>
- /// <code lang="VB">
- /// Public Sub Run()
- /// Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive."
- /// Using zip1 As ZipFile = New ZipFile
- /// zip1.AddEntry("Readme.txt", Content)
- /// zip1.AddFile("MyDocuments\Resume.doc", "files")
- /// zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G"))
- /// zip1.Save("Content.zip")
- /// End Using
- /// End Sub
- /// </code>
- /// </example>
- public ZipEntry AddEntry(string entryName, string content)
- {
- #if SILVERLIGHT
- return AddEntry(entryName, content, System.Text.Encoding.UTF8);
- #else
- return AddEntry(entryName, content, System.Text.Encoding.Default);
- #endif
- }
- /// <summary>
- /// Adds a named entry into the zip archive, taking content for the entry
- /// from a string, and using the specified text encoding.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// Calling this method creates an entry using the given fileName and
- /// directory path within the archive. There is no need for a file by the
- /// given name to exist in the filesystem; the name is used within the zip
- /// archive only.
- /// </para>
- ///
- /// <para>
- /// The content for the entry, a string value, is encoded using the given
- /// text encoding. A BOM (byte-order-mark) is emitted into the file, if the
- /// Encoding parameter is set for that.
- /// </para>
- ///
- /// <para>
- /// Most Encoding classes support a constructor that accepts a boolean,
- /// indicating whether to emit a BOM or not. For example see <see
- /// cref="System.Text.UTF8Encoding(bool)"/>.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use within the archive for the entry.
- /// </param>
- ///
- /// <param name="content">
- /// The content of the file, should it be extracted from the zip.
- /// </param>
- ///
- /// <param name="encoding">
- /// The text encoding to use when encoding the string. Be aware: This is
- /// distinct from the text encoding used to encode the fileName, as specified
- /// in <see cref="ProvisionalAlternateEncoding" />.
- /// </param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- ///
- public ZipEntry AddEntry(string entryName, string content, System.Text.Encoding encoding)
- {
- // cannot employ a using clause here. We need the stream to
- // persist after exit from this method.
- var ms = new MemoryStream();
- // cannot use a using clause here; StreamWriter takes
- // ownership of the stream and Disposes it before we are ready.
- var sw = new StreamWriter(ms, encoding);
- sw.Write(content);
- sw.Flush();
- // reset to allow reading later
- ms.Seek(0, SeekOrigin.Begin);
- return AddEntry(entryName, ms);
- // must not dispose the MemoryStream - it will be used later.
- }
- /// <summary>
- /// Create an entry in the <c>ZipFile</c> using the given <c>Stream</c>
- /// as input. The entry will have the given filename.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// The application should provide an open, readable stream; in this case it
- /// will be read during the call to <see cref="ZipFile.Save()"/> or one of
- /// its overloads.
- /// </para>
- ///
- /// <para>
- /// The passed stream will be read from its current position. If
- /// necessary, callers should set the position in the stream before
- /// calling AddEntry(). This might be appropriate when using this method
- /// with a MemoryStream, for example.
- /// </para>
- ///
- /// <para>
- /// In cases where a large number of streams will be added to the
- /// <c>ZipFile</c>, the application may wish to avoid maintaining all of the
- /// streams open simultaneously. To handle this situation, the application
- /// should use the <see cref="AddEntry(string, OpenDelegate, CloseDelegate)"/>
- /// overload.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// <para>
- /// This example adds a single entry to a <c>ZipFile</c> via a <c>Stream</c>.
- /// </para>
- ///
- /// <code lang="C#">
- /// String zipToCreate = "Content.zip";
- /// String fileNameInArchive = "Content-From-Stream.bin";
- /// using (System.IO.Stream streamToRead = MyStreamOpener())
- /// {
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// ZipEntry entry= zip.AddEntry(fileNameInArchive, streamToRead);
- /// zip.AddFile("Readme.txt");
- /// zip.Save(zipToCreate); // the stream is read implicitly here
- /// }
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Dim zipToCreate As String = "Content.zip"
- /// Dim fileNameInArchive As String = "Content-From-Stream.bin"
- /// Using streamToRead as System.IO.Stream = MyStreamOpener()
- /// Using zip As ZipFile = New ZipFile()
- /// Dim entry as ZipEntry = zip.AddEntry(fileNameInArchive, streamToRead)
- /// zip.AddFile("Readme.txt")
- /// zip.Save(zipToCreate) '' the stream is read implicitly, here
- /// End Using
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateEntry(string, System.IO.Stream)"/>
- ///
- /// <param name="entryName">
- /// The name, including any path, which is shown in the zip file for the added
- /// entry.
- /// </param>
- /// <param name="stream">
- /// The input stream from which to grab content for the file
- /// </param>
- /// <returns>The <c>ZipEntry</c> added.</returns>
- public ZipEntry AddEntry(string entryName, Stream stream)
- {
- ZipEntry ze = ZipEntry.CreateForStream(entryName, stream);
- ze.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now);
- if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName);
- return _InternalAddEntry(ze);
- }
- /// <summary>
- /// Add a ZipEntry for which content is written directly by the application.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// When the application needs to write the zip entry data, use this
- /// method to add the ZipEntry. For example, in the case that the
- /// application wishes to write the XML representation of a DataSet into
- /// a ZipEntry, the application can use this method to do so.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- ///
- /// <para>
- /// About progress events: When using the WriteDelegate, DotNetZip does
- /// not issue any SaveProgress events with <c>EventType</c> = <see
- /// cref="ZipProgressEventType.Saving_EntryBytesRead">
- /// Saving_EntryBytesRead</see>. (This is because it is the
- /// application's code that runs in WriteDelegate - there's no way for
- /// DotNetZip to know when to issue a EntryBytesRead event.)
- /// Applications that want to update a progress bar or similar status
- /// indicator should do so from within the WriteDelegate
- /// itself. DotNetZip will issue the other SaveProgress events,
- /// including <see cref="ZipProgressEventType.Saving_Started">
- /// Saving_Started</see>,
- /// <see cref="ZipProgressEventType.Saving_BeforeWriteEntry">
- /// Saving_BeforeWriteEntry</see>, and <see
- /// cref="ZipProgressEventType.Saving_AfterWriteEntry">
- /// Saving_AfterWriteEntry</see>.
- /// </para>
- ///
- /// <para>
- /// Note: When you use PKZip encryption, it's normally necessary to
- /// compute the CRC of the content to be encrypted, before compressing or
- /// encrypting it. Therefore, when using PKZip encryption with a
- /// WriteDelegate, the WriteDelegate CAN BE called twice: once to compute
- /// the CRC, and the second time to potentially compress and
- /// encrypt. Surprising, but true. This is because PKWARE specified that
- /// the encryption initialization data depends on the CRC.
- /// If this happens, for each call of the delegate, your
- /// application must stream the same entry data in its entirety. If your
- /// application writes different data during the second call, it will
- /// result in a corrupt zip file.
- /// </para>
- ///
- /// <para>
- /// The double-read behavior happens with all types of entries, not only
- /// those that use WriteDelegate. It happens if you add an entry from a
- /// filesystem file, or using a string, or a stream, or an opener/closer
- /// pair. But in those cases, DotNetZip takes care of reading twice; in
- /// the case of the WriteDelegate, the application code gets invoked
- /// twice. Be aware.
- /// </para>
- ///
- /// <para>
- /// As you can imagine, this can cause performance problems for large
- /// streams, and it can lead to correctness problems when you use a
- /// <c>WriteDelegate</c>. This is a pretty big pitfall. There are two
- /// ways to avoid it. First, and most preferred: don't use PKZIP
- /// encryption. If you use the WinZip AES encryption, this problem
- /// doesn't occur, because the encryption protocol doesn't require the CRC
- /// up front. Second: if you do choose to use PKZIP encryption, write out
- /// to a non-seekable stream (like standard output, or the
- /// Response.OutputStream in an ASP.NET application). In this case,
- /// DotNetZip will use an alternative encryption protocol that does not
- /// rely on the CRC of the content. This also implies setting bit 3 in
- /// the zip entry, which still presents problems for some zip tools.
- /// </para>
- ///
- /// <para>
- /// In the future I may modify DotNetZip to *always* use bit 3 when PKZIP
- /// encryption is in use. This seems like a win overall, but there will
- /// be some work involved. If you feel strongly about it, visit the
- /// DotNetZip forums and vote up <see
- /// href="http://dotnetzip.codeplex.com/workitem/13686">the Workitem
- /// tracking this issue</see>.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <param name="entryName">the name of the entry to add</param>
- /// <param name="writer">the delegate which will write the entry content</param>
- /// <returns>the ZipEntry added</returns>
- ///
- /// <example>
- ///
- /// This example shows an application filling a DataSet, then saving the
- /// contents of that DataSet as XML, into a ZipEntry in a ZipFile, using an
- /// anonymous delegate in C#. The DataSet XML is never saved to a disk file.
- ///
- /// <code lang="C#">
- /// var c1= new System.Data.SqlClient.SqlConnection(connstring1);
- /// var da = new System.Data.SqlClient.SqlDataAdapter()
- /// {
- /// SelectCommand= new System.Data.SqlClient.SqlCommand(strSelect, c1)
- /// };
- ///
- /// DataSet ds1 = new DataSet();
- /// da.Fill(ds1, "Invoices");
- ///
- /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
- /// {
- /// zip.AddEntry(zipEntryName, (name,stream) => ds1.WriteXml(stream) );
- /// zip.Save(zipFileName);
- /// }
- /// </code>
- /// </example>
- ///
- /// <example>
- ///
- /// This example uses an anonymous method in C# as the WriteDelegate to provide
- /// the data for the ZipEntry. The example is a bit contrived - the
- /// <c>AddFile()</c> method is a simpler way to insert the contents of a file
- /// into an entry in a zip file. On the other hand, if there is some sort of
- /// processing or transformation of the file contents required before writing,
- /// the application could use the <c>WriteDelegate</c> to do it, in this way.
- ///
- /// <code lang="C#">
- /// using (var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ))
- /// {
- /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
- /// {
- /// zip.AddEntry(zipEntryName, (name,output) =>
- /// {
- /// byte[] buffer = new byte[BufferSize];
- /// int n;
- /// while ((n = input.Read(buffer, 0, buffer.Length)) != 0)
- /// {
- /// // could transform the data here...
- /// output.Write(buffer, 0, n);
- /// // could update a progress bar here
- /// }
- /// });
- ///
- /// zip.Save(zipFileName);
- /// }
- /// }
- /// </code>
- /// </example>
- ///
- /// <example>
- ///
- /// This example uses a named delegate in VB to write data for the given
- /// ZipEntry (VB9 does not have anonymous delegates). The example here is a bit
- /// contrived - a simpler way to add the contents of a file to a ZipEntry is to
- /// simply use the appropriate <c>AddFile()</c> method. The key scenario for
- /// which the <c>WriteDelegate</c> makes sense is saving a DataSet, in XML
- /// format, to the zip file. The DataSet can write XML to a stream, and the
- /// WriteDelegate is the perfect place to write into the zip file. There may be
- /// other data structures that can write to a stream, but cannot be read as a
- /// stream. The <c>WriteDelegate</c> would be appropriate for those cases as
- /// well.
- ///
- /// <code lang="VB">
- /// Private Sub WriteEntry (ByVal name As String, ByVal output As Stream)
- /// Using input As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
- /// Dim n As Integer = -1
- /// Dim buffer As Byte() = New Byte(BufferSize){}
- /// Do While n <> 0
- /// n = input.Read(buffer, 0, buffer.Length)
- /// output.Write(buffer, 0, n)
- /// Loop
- /// End Using
- /// End Sub
- ///
- /// Public Sub Run()
- /// Using zip = New ZipFile
- /// zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry))
- /// zip.Save(zipFileName)
- /// End Using
- /// End Sub
- /// </code>
- /// </example>
- public ZipEntry AddEntry(string entryName, WriteDelegate writer)
- {
- ZipEntry ze = ZipEntry.CreateForWriter(entryName, writer);
- if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName);
- return _InternalAddEntry(ze);
- }
- /// <summary>
- /// Add an entry, for which the application will provide a stream
- /// containing the entry data, on a just-in-time basis.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// In cases where the application wishes to open the stream that
- /// holds the content for the ZipEntry, on a just-in-time basis, the
- /// application can use this method. The application provides an
- /// opener delegate that will be called by the DotNetZip library to
- /// obtain a readable stream that can be read to get the bytes for
- /// the given entry. Typically, this delegate opens a stream.
- /// Optionally, the application can provide a closer delegate as
- /// well, which will be called by DotNetZip when all bytes have been
- /// read from the entry.
- /// </para>
- ///
- /// <para>
- /// These delegates are called from within the scope of the call to
- /// ZipFile.Save().
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- ///
- /// This example uses anonymous methods in C# to open and close the
- /// source stream for the content for a zip entry.
- ///
- /// <code lang="C#">
- /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
- /// {
- /// zip.AddEntry(zipEntryName,
- /// (name) => File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ),
- /// (name, stream) => stream.Close()
- /// );
- ///
- /// zip.Save(zipFileName);
- /// }
- /// </code>
- ///
- /// </example>
- ///
- /// <example>
- ///
- /// This example uses delegates in VB.NET to open and close the
- /// the source stream for the content for a zip entry. VB 9.0 lacks
- /// support for "Sub" lambda expressions, and so the CloseDelegate must
- /// be an actual, named Sub.
- ///
- /// <code lang="VB">
- ///
- /// Function MyStreamOpener(ByVal entryName As String) As Stream
- /// '' This simply opens a file. You probably want to do somethinig
- /// '' more involved here: open a stream to read from a database,
- /// '' open a stream on an HTTP connection, and so on.
- /// Return File.OpenRead(entryName)
- /// End Function
- ///
- /// Sub MyStreamCloser(entryName As String, stream As Stream)
- /// stream.Close()
- /// End Sub
- ///
- /// Public Sub Run()
- /// Dim dirToZip As String = "fodder"
- /// Dim zipFileToCreate As String = "Archive.zip"
- /// Dim opener As OpenDelegate = AddressOf MyStreamOpener
- /// Dim closer As CloseDelegate = AddressOf MyStreamCloser
- /// Dim numFilestoAdd As Int32 = 4
- /// Using zip As ZipFile = New ZipFile
- /// Dim i As Integer
- /// For i = 0 To numFilesToAdd - 1
- /// zip.AddEntry(String.Format("content-{0:000}.txt"), opener, closer)
- /// Next i
- /// zip.Save(zipFileToCreate)
- /// End Using
- /// End Sub
- ///
- /// </code>
- /// </example>
- ///
- /// <param name="entryName">the name of the entry to add</param>
- /// <param name="opener">
- /// the delegate that will be invoked by ZipFile.Save() to get the
- /// readable stream for the given entry. ZipFile.Save() will call
- /// read on this stream to obtain the data for the entry. This data
- /// will then be compressed and written to the newly created zip
- /// file.
- /// </param>
- /// <param name="closer">
- /// the delegate that will be invoked to close the stream. This may
- /// be null (Nothing in VB), in which case no call is makde to close
- /// the stream.
- /// </param>
- /// <returns>the ZipEntry added</returns>
- ///
- public ZipEntry AddEntry(string entryName, OpenDelegate opener, CloseDelegate closer)
- {
- ZipEntry ze = ZipEntry.CreateForJitStreamProvider(entryName, opener, closer);
- ze.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now);
- if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName);
- return _InternalAddEntry(ze);
- }
- private ZipEntry _InternalAddEntry(ZipEntry ze)
- {
- // stamp all the props onto the entry
- ze._container = new ZipContainer(this);
- ze.CompressionMethod = this.CompressionMethod;
- ze.CompressionLevel = this.CompressionLevel;
- ze.ExtractExistingFile = this.ExtractExistingFile;
- ze.ZipErrorAction = this.ZipErrorAction;
- ze.SetCompression = this.SetCompression;
- ze.AlternateEncoding = this.AlternateEncoding;
- ze.AlternateEncodingUsage = this.AlternateEncodingUsage;
- ze.Password = this._Password;
- ze.Encryption = this.Encryption;
- ze.EmitTimesInWindowsFormatWhenSaving = this._emitNtfsTimes;
- ze.EmitTimesInUnixFormatWhenSaving = this._emitUnixTimes;
- //string key = DictionaryKeyForEntry(ze);
- InternalAddEntry(ze.FileName,ze);
- AfterAddEntry(ze);
- return ze;
- }
- /// <summary>
- /// Updates the given entry in the <c>ZipFile</c>, using the given
- /// string as content for the <c>ZipEntry</c>.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// Calling this method is equivalent to removing the <c>ZipEntry</c> for
- /// the given file name and directory path, if it exists, and then calling
- /// <see cref="AddEntry(String,String)" />. See the documentation for
- /// that method for further explanation. The string content is encoded
- /// using the default encoding for the machine, or on Silverlight, using
- /// UTF-8. This encoding is distinct from the encoding used for the
- /// filename itself. See <see cref="AlternateEncoding"/>.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use within the archive for the entry.
- /// </param>
- ///
- /// <param name="content">
- /// The content of the file, should it be extracted from the zip.
- /// </param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- ///
- public ZipEntry UpdateEntry(string entryName, string content)
- {
- #if SILVERLIGHT
- return UpdateEntry(entryName, content, System.Text.Encoding.UTF8);
- #else
- return UpdateEntry(entryName, content, System.Text.Encoding.Default);
- #endif
- }
- /// <summary>
- /// Updates the given entry in the <c>ZipFile</c>, using the given string as
- /// content for the <c>ZipEntry</c>.
- /// </summary>
- ///
- /// <remarks>
- /// Calling this method is equivalent to removing the <c>ZipEntry</c> for the
- /// given file name and directory path, if it exists, and then calling <see
- /// cref="AddEntry(String,String, System.Text.Encoding)" />. See the
- /// documentation for that method for further explanation.
- /// </remarks>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use within the archive for the entry.
- /// </param>
- ///
- /// <param name="content">
- /// The content of the file, should it be extracted from the zip.
- /// </param>
- ///
- /// <param name="encoding">
- /// The text encoding to use when encoding the string. Be aware: This is
- /// distinct from the text encoding used to encode the filename. See <see
- /// cref="AlternateEncoding" />.
- /// </param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- ///
- public ZipEntry UpdateEntry(string entryName, string content, System.Text.Encoding encoding)
- {
- RemoveEntryForUpdate(entryName);
- return AddEntry(entryName, content, encoding);
- }
- /// <summary>
- /// Updates the given entry in the <c>ZipFile</c>, using the given delegate
- /// as the source for content for the <c>ZipEntry</c>.
- /// </summary>
- ///
- /// <remarks>
- /// Calling this method is equivalent to removing the <c>ZipEntry</c> for the
- /// given file name and directory path, if it exists, and then calling <see
- /// cref="AddEntry(String,WriteDelegate)" />. See the
- /// documentation for that method for further explanation.
- /// </remarks>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use within the archive for the entry.
- /// </param>
- ///
- /// <param name="writer">the delegate which will write the entry content.</param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- ///
- public ZipEntry UpdateEntry(string entryName, WriteDelegate writer)
- {
- RemoveEntryForUpdate(entryName);
- return AddEntry(entryName, writer);
- }
- /// <summary>
- /// Updates the given entry in the <c>ZipFile</c>, using the given delegates
- /// to open and close the stream that provides the content for the <c>ZipEntry</c>.
- /// </summary>
- ///
- /// <remarks>
- /// Calling this method is equivalent to removing the <c>ZipEntry</c> for the
- /// given file name and directory path, if it exists, and then calling <see
- /// cref="AddEntry(String,OpenDelegate, CloseDelegate)" />. See the
- /// documentation for that method for further explanation.
- /// </remarks>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use within the archive for the entry.
- /// </param>
- ///
- /// <param name="opener">
- /// the delegate that will be invoked to open the stream
- /// </param>
- /// <param name="closer">
- /// the delegate that will be invoked to close the stream
- /// </param>
- ///
- /// <returns>The <c>ZipEntry</c> added or updated.</returns>
- ///
- public ZipEntry UpdateEntry(string entryName, OpenDelegate opener, CloseDelegate closer)
- {
- RemoveEntryForUpdate(entryName);
- return AddEntry(entryName, opener, closer);
- }
- /// <summary>
- /// Updates the given entry in the <c>ZipFile</c>, using the given stream as
- /// input, and the given filename and given directory Path.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// Calling the method is equivalent to calling <c>RemoveEntry()</c> if an
- /// entry by the same name already exists, and then calling <c>AddEntry()</c>
- /// with the given <c>fileName</c> and stream.
- /// </para>
- ///
- /// <para>
- /// The stream must be open and readable during the call to
- /// <c>ZipFile.Save</c>. You can dispense the stream on a just-in-time basis
- /// using the <see cref="ZipEntry.InputStream"/> property. Check the
- /// documentation of that property for more information.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to the
- /// <c>ZipEntry</c> added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(string, System.IO.Stream)"/>
- /// <seealso cref="Ionic.Zip.ZipEntry.InputStream"/>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use within the archive for the entry.
- /// </param>
- ///
- /// <param name="stream">The input stream from which to read file data.</param>
- /// <returns>The <c>ZipEntry</c> added.</returns>
- public ZipEntry UpdateEntry(string entryName, Stream stream)
- {
- RemoveEntryForUpdate(entryName);
- return AddEntry(entryName, stream);
- }
- private void RemoveEntryForUpdate(string entryName)
- {
- if (String.IsNullOrEmpty(entryName))
- throw new ArgumentNullException("entryName");
- string directoryPathInArchive = null;
- if (entryName.IndexOf('\\') != -1)
- {
- directoryPathInArchive = Path.GetDirectoryName(entryName);
- entryName = Path.GetFileName(entryName);
- }
- var key = ZipEntry.NameInArchive(entryName, directoryPathInArchive);
- if (this[key] != null)
- this.RemoveEntry(key);
- }
- /// <summary>
- /// Add an entry into the zip archive using the given filename and
- /// directory path within the archive, and the given content for the
- /// file. No file is created in the filesystem.
- /// </summary>
- ///
- /// <param name="byteContent">The data to use for the entry.</param>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use within the archive for the entry.
- /// </param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- public ZipEntry AddEntry(string entryName, byte[] byteContent)
- {
- if (byteContent == null) throw new ArgumentException("bad argument", "byteContent");
- var ms = new MemoryStream(byteContent);
- return AddEntry(entryName, ms);
- }
- /// <summary>
- /// Updates the given entry in the <c>ZipFile</c>, using the given byte
- /// array as content for the entry.
- /// </summary>
- ///
- /// <remarks>
- /// Calling this method is equivalent to removing the <c>ZipEntry</c>
- /// for the given filename and directory path, if it exists, and then
- /// calling <see cref="AddEntry(String,byte[])" />. See the
- /// documentation for that method for further explanation.
- /// </remarks>
- ///
- /// <param name="entryName">
- /// The name, including any path, to use within the archive for the entry.
- /// </param>
- ///
- /// <param name="byteContent">The content to use for the <c>ZipEntry</c>.</param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- ///
- public ZipEntry UpdateEntry(string entryName, byte[] byteContent)
- {
- RemoveEntryForUpdate(entryName);
- return AddEntry(entryName, byteContent);
- }
- // private string DictionaryKeyForEntry(ZipEntry ze1)
- // {
- // var filename = SharedUtilities.NormalizePathForUseInZipFile(ze1.FileName);
- // return filename;
- // }
- /// <summary>
- /// Adds the contents of a filesystem directory to a Zip file archive.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// The name of the directory may be a relative path or a fully-qualified
- /// path. Any files within the named directory are added to the archive. Any
- /// subdirectories within the named directory are also added to the archive,
- /// recursively.
- /// </para>
- ///
- /// <para>
- /// Top-level entries in the named directory will appear as top-level entries
- /// in the zip archive. Entries in subdirectories in the named directory will
- /// result in entries in subdirectories in the zip archive.
- /// </para>
- ///
- /// <para>
- /// If you want the entries to appear in a containing directory in the zip
- /// archive itself, then you should call the AddDirectory() overload that
- /// allows you to explicitly specify a directory path for use in the archive.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to each
- /// ZipEntry added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/>
- ///
- /// <overloads>This method has 2 overloads.</overloads>
- ///
- /// <param name="directoryName">The name of the directory to add.</param>
- /// <returns>The <c>ZipEntry</c> added.</returns>
- public ZipEntry AddDirectory(string directoryName)
- {
- return AddDirectory(directoryName, null);
- }
- /// <summary>
- /// Adds the contents of a filesystem directory to a Zip file archive,
- /// overriding the path to be used for entries in the archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// The name of the directory may be a relative path or a fully-qualified
- /// path. The add operation is recursive, so that any files or subdirectories
- /// within the name directory are also added to the archive.
- /// </para>
- ///
- /// <para>
- /// Top-level entries in the named directory will appear as top-level entries
- /// in the zip archive. Entries in subdirectories in the named directory will
- /// result in entries in subdirectories in the zip archive.
- /// </para>
- ///
- /// <para>
- /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
- /// cref="Password"/>, <see cref="SetCompression"/>, <see
- /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
- /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
- /// respective values at the time of this call will be applied to each
- /// ZipEntry added.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// <para>
- /// In this code, calling the ZipUp() method with a value of "c:\reports" for
- /// the directory parameter will result in a zip file structure in which all
- /// entries are contained in a toplevel "reports" directory.
- /// </para>
- ///
- /// <code lang="C#">
- /// public void ZipUp(string targetZip, string directory)
- /// {
- /// using (var zip = new ZipFile())
- /// {
- /// zip.AddDirectory(directory, System.IO.Path.GetFileName(directory));
- /// zip.Save(targetZip);
- /// }
- /// }
- /// </code>
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string, string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string, string)"/>
- /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string, string)"/>
- ///
- /// <param name="directoryName">The name of the directory to add.</param>
- ///
- /// <param name="directoryPathInArchive">
- /// Specifies a directory path to use to override any path in the
- /// DirectoryName. This path may, or may not, correspond to a real directory
- /// in the current filesystem. If the zip is later extracted, this is the
- /// path used for the extracted file or directory. Passing <c>null</c>
- /// (<c>Nothing</c> in VB) or the empty string ("") will insert the items at
- /// the root path within the archive.
- /// </param>
- ///
- /// <returns>The <c>ZipEntry</c> added.</returns>
- public ZipEntry AddDirectory(string directoryName, string directoryPathInArchive)
- {
- return AddOrUpdateDirectoryImpl(directoryName, directoryPathInArchive, AddOrUpdateAction.AddOnly);
- }
- /// <summary>
- /// Creates a directory in the zip archive.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// Use this when you want to create a directory in the archive but there is
- /// no corresponding filesystem representation for that directory.
- /// </para>
- ///
- /// <para>
- /// You will probably not need to do this in your code. One of the only times
- /// you will want to do this is if you want an empty directory in the zip
- /// archive. The reason: if you add a file to a zip archive that is stored
- /// within a multi-level directory, all of the directory tree is implicitly
- /// created in the zip archive.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <param name="directoryNameInArchive">
- /// The name of the directory to create in the archive.
- /// </param>
- /// <returns>The <c>ZipEntry</c> added.</returns>
- public ZipEntry AddDirectoryByName(string directoryNameInArchive)
- {
- // workitem 9073
- ZipEntry dir = ZipEntry.CreateFromNothing(directoryNameInArchive);
- dir._container = new ZipContainer(this);
- dir.MarkAsDirectory();
- dir.AlternateEncoding = this.AlternateEncoding; // workitem 8984
- dir.AlternateEncodingUsage = this.AlternateEncodingUsage;
- dir.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now);
- dir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes;
- dir.EmitTimesInUnixFormatWhenSaving = _emitUnixTimes;
- dir._Source = ZipEntrySource.Stream;
- //string key = DictionaryKeyForEntry(dir);
- InternalAddEntry(dir.FileName,dir);
- AfterAddEntry(dir);
- return dir;
- }
- private ZipEntry AddOrUpdateDirectoryImpl(string directoryName,
- string rootDirectoryPathInArchive,
- AddOrUpdateAction action)
- {
- if (rootDirectoryPathInArchive == null)
- {
- rootDirectoryPathInArchive = "";
- }
- return AddOrUpdateDirectoryImpl(directoryName, rootDirectoryPathInArchive, action, true, 0);
- }
- internal void InternalAddEntry(String name, ZipEntry entry)
- {
- _entries.Add(name, entry);
- if (!_entriesInsensitive.ContainsKey(name))
- _entriesInsensitive.Add(name, entry);
- _zipEntriesAsList = null;
- _contentsChanged = true;
- }
- private ZipEntry AddOrUpdateDirectoryImpl(string directoryName,
- string rootDirectoryPathInArchive,
- AddOrUpdateAction action,
- bool recurse,
- int level)
- {
- if (Verbose)
- StatusMessageTextWriter.WriteLine("{0} {1}...",
- (action == AddOrUpdateAction.AddOnly) ? "adding" : "Adding or updating",
- directoryName);
- if (level == 0)
- {
- _addOperationCanceled = false;
- OnAddStarted();
- }
- // workitem 13371
- if (_addOperationCanceled)
- return null;
- string dirForEntries = rootDirectoryPathInArchive;
- ZipEntry baseDir = null;
- if (level > 0)
- {
- int f = directoryName.Length;
- for (int i = level; i > 0; i--)
- f = directoryName.LastIndexOfAny("/\\".ToCharArray(), f - 1, f - 1);
- dirForEntries = directoryName.Substring(f + 1);
- dirForEntries = Path.Combine(rootDirectoryPathInArchive, dirForEntries);
- }
- // if not top level, or if the root is non-empty, then explicitly add the directory
- if (level > 0 || rootDirectoryPathInArchive != "")
- {
- baseDir = ZipEntry.CreateFromFile(directoryName, dirForEntries);
- baseDir._container = new ZipContainer(this);
- baseDir.AlternateEncoding = this.AlternateEncoding; // workitem 6410
- baseDir.AlternateEncodingUsage = this.AlternateEncodingUsage;
- baseDir.MarkAsDirectory();
- baseDir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes;
- baseDir.EmitTimesInUnixFormatWhenSaving = _emitUnixTimes;
- // add the directory only if it does not exist.
- // It's not an error if it already exists.
- if (!_entries.ContainsKey(baseDir.FileName))
- {
- InternalAddEntry(baseDir.FileName,baseDir);
- AfterAddEntry(baseDir);
- }
- dirForEntries = baseDir.FileName;
- }
- if (!_addOperationCanceled)
- {
- String[] filenames = Directory.GetFiles(directoryName);
- if (recurse)
- {
- // add the files:
- foreach (String filename in filenames)
- {
- if (_addOperationCanceled) break;
- if (action == AddOrUpdateAction.AddOnly)
- AddFile(filename, dirForEntries);
- else
- UpdateFile(filename, dirForEntries);
- }
- if (!_addOperationCanceled)
- {
- // add the subdirectories:
- String[] dirnames = Directory.GetDirectories(directoryName);
- foreach (String dir in dirnames)
- {
- // workitem 8617: Optionally traverse reparse points
- #if SILVERLIGHT
- #elif NETCF
- FileAttributes fileAttrs = (FileAttributes) NetCfFile.GetAttributes(dir);
- #else
- FileAttributes fileAttrs = System.IO.File.GetAttributes(dir);
- #endif
- if (this.AddDirectoryWillTraverseReparsePoints
- #if !SILVERLIGHT
- || ((fileAttrs & FileAttributes.ReparsePoint) == 0)
- #endif
- )
- AddOrUpdateDirectoryImpl(dir, rootDirectoryPathInArchive, action, recurse, level + 1);
- }
- }
- }
- }
- if (level == 0)
- OnAddCompleted();
- return baseDir;
- }
- }
- }
|