| // 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 OfficeOpenXml.Packaging.Ionic.Zip |
| { |
| internal 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="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); |
| _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; |
| } |
| |
| } |
| |
| } |