kopia lustrzana https://github.com/dl2alf/AirScout
299 wiersze
12 KiB
C#
299 wiersze
12 KiB
C#
// ZipFile.Extract.cs
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) 2009 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-July-31 14:45:18>
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// This module defines the methods for Extract operations on zip files.
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Ionic.Zip
|
|
{
|
|
|
|
public partial class ZipFile
|
|
{
|
|
|
|
/// <summary>
|
|
/// Extracts all of the items in the zip archive, to the specified path in the
|
|
/// filesystem. The path can be relative or fully-qualified.
|
|
/// </summary>
|
|
///
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This method will extract all entries in the <c>ZipFile</c> to the
|
|
/// specified path.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// If an extraction of a file from the zip archive would overwrite an
|
|
/// existing file in the filesystem, the action taken is dictated by the
|
|
/// ExtractExistingFile property, which overrides any setting you may have
|
|
/// made on individual ZipEntry instances. By default, if you have not
|
|
/// set that property on the <c>ZipFile</c> instance, the entry will not
|
|
/// be extracted, the existing file will not be overwritten and an
|
|
/// exception will be thrown. To change this, set the property, or use the
|
|
/// <see cref="ZipFile.ExtractAll(string,
|
|
/// Ionic.Zip.ExtractExistingFileAction)" /> overload that allows you to
|
|
/// specify an ExtractExistingFileAction parameter.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// The action to take when an extract would overwrite an existing file
|
|
/// applies to all entries. If you want to set this on a per-entry basis,
|
|
/// then you must use one of the <see
|
|
/// cref="ZipEntry.Extract()">ZipEntry.Extract</see> methods.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// This method will send verbose output messages to the <see
|
|
/// cref="StatusMessageTextWriter"/>, if it is set on the <c>ZipFile</c>
|
|
/// instance.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// You may wish to take advantage of the <c>ExtractProgress</c> event.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// About timestamps: When extracting a file entry from a zip archive, the
|
|
/// extracted file gets the last modified time of the entry as stored in
|
|
/// the archive. The archive may also store extended file timestamp
|
|
/// information, including last accessed and created times. If these are
|
|
/// present in the <c>ZipEntry</c>, then the extracted file will also get
|
|
/// these times.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// A Directory entry is somewhat different. It will get the times as
|
|
/// described for a file entry, but, if there are file entries in the zip
|
|
/// archive that, when extracted, appear in the just-created directory,
|
|
/// then when those file entries are extracted, the last modified and last
|
|
/// accessed times of the directory will change, as a side effect. The
|
|
/// result is that after an extraction of a directory and a number of
|
|
/// files within the directory, the last modified and last accessed
|
|
/// timestamps on the directory will reflect the time that the last file
|
|
/// was extracted into the directory, rather than the time stored in the
|
|
/// zip archive for the directory.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// To compensate, when extracting an archive with <c>ExtractAll</c>,
|
|
/// DotNetZip will extract all the file and directory entries as described
|
|
/// above, but it will then make a second pass on the directories, and
|
|
/// reset the times on the directories to reflect what is stored in the
|
|
/// zip archive.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// This compensation is performed only within the context of an
|
|
/// <c>ExtractAll</c>. If you call <c>ZipEntry.Extract</c> on a directory
|
|
/// entry, the timestamps on directory in the filesystem will reflect the
|
|
/// times stored in the zip. If you then call <c>ZipEntry.Extract</c> on
|
|
/// a file entry, which is extracted into the directory, the timestamps on
|
|
/// the directory will be updated to the current time.
|
|
/// </para>
|
|
/// </remarks>
|
|
///
|
|
/// <example>
|
|
/// This example extracts all the entries in a zip archive file, to the
|
|
/// specified target directory. The extraction will overwrite any
|
|
/// existing files silently.
|
|
///
|
|
/// <code>
|
|
/// String TargetDirectory= "unpack";
|
|
/// using(ZipFile zip= ZipFile.Read(ZipFileToExtract))
|
|
/// {
|
|
/// zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently;
|
|
/// zip.ExtractAll(TargetDirectory);
|
|
/// }
|
|
/// </code>
|
|
///
|
|
/// <code lang="VB">
|
|
/// Dim TargetDirectory As String = "unpack"
|
|
/// Using zip As ZipFile = ZipFile.Read(ZipFileToExtract)
|
|
/// zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently
|
|
/// zip.ExtractAll(TargetDirectory)
|
|
/// End Using
|
|
/// </code>
|
|
/// </example>
|
|
///
|
|
/// <seealso cref="Ionic.Zip.ZipFile.ExtractProgress"/>
|
|
/// <seealso cref="Ionic.Zip.ZipFile.ExtractExistingFile"/>
|
|
///
|
|
/// <param name="path">
|
|
/// The path to which the contents of the zipfile will be extracted.
|
|
/// The path can be relative or fully-qualified.
|
|
/// </param>
|
|
///
|
|
public void ExtractAll(string path)
|
|
{
|
|
_InternalExtractAll(path, true);
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Extracts all of the items in the zip archive, to the specified path in the
|
|
/// filesystem, using the specified behavior when extraction would overwrite an
|
|
/// existing file.
|
|
/// </summary>
|
|
///
|
|
/// <remarks>
|
|
///
|
|
/// <para>
|
|
/// This method will extract all entries in the <c>ZipFile</c> to the specified
|
|
/// path. For an extraction that would overwrite an existing file, the behavior
|
|
/// is dictated by <paramref name="extractExistingFile"/>, which overrides any
|
|
/// setting you may have made on individual ZipEntry instances.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// The action to take when an extract would overwrite an existing file
|
|
/// applies to all entries. If you want to set this on a per-entry basis,
|
|
/// then you must use <see cref="ZipEntry.Extract(String,
|
|
/// ExtractExistingFileAction)" /> or one of the similar methods.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// Calling this method is equivalent to setting the <see
|
|
/// cref="ExtractExistingFile"/> property and then calling <see
|
|
/// cref="ExtractAll(String)"/>.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// This method will send verbose output messages to the
|
|
/// <see cref="StatusMessageTextWriter"/>, if it is set on the <c>ZipFile</c> instance.
|
|
/// </para>
|
|
/// </remarks>
|
|
///
|
|
/// <example>
|
|
/// This example extracts all the entries in a zip archive file, to the
|
|
/// specified target directory. It does not overwrite any existing files.
|
|
/// <code>
|
|
/// String TargetDirectory= "c:\\unpack";
|
|
/// using(ZipFile zip= ZipFile.Read(ZipFileToExtract))
|
|
/// {
|
|
/// zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite);
|
|
/// }
|
|
/// </code>
|
|
///
|
|
/// <code lang="VB">
|
|
/// Dim TargetDirectory As String = "c:\unpack"
|
|
/// Using zip As ZipFile = ZipFile.Read(ZipFileToExtract)
|
|
/// zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite)
|
|
/// End Using
|
|
/// </code>
|
|
/// </example>
|
|
///
|
|
/// <param name="path">
|
|
/// The path to which the contents of the zipfile will be extracted.
|
|
/// The path can be relative or fully-qualified.
|
|
/// </param>
|
|
///
|
|
/// <param name="extractExistingFile">
|
|
/// The action to take if extraction would overwrite an existing file.
|
|
/// </param>
|
|
/// <seealso cref="ExtractSelectedEntries(String,ExtractExistingFileAction)"/>
|
|
public void ExtractAll(string path, ExtractExistingFileAction extractExistingFile)
|
|
{
|
|
ExtractExistingFile = extractExistingFile;
|
|
_InternalExtractAll(path, true);
|
|
}
|
|
|
|
|
|
private void _InternalExtractAll(string path, bool overrideExtractExistingProperty)
|
|
{
|
|
bool header = Verbose;
|
|
_inExtractAll = true;
|
|
try
|
|
{
|
|
OnExtractAllStarted(path);
|
|
|
|
int n = 0;
|
|
foreach (ZipEntry e in _entries.Values)
|
|
{
|
|
if (header)
|
|
{
|
|
StatusMessageTextWriter.WriteLine("\n{1,-22} {2,-8} {3,4} {4,-8} {0}",
|
|
"Name", "Modified", "Size", "Ratio", "Packed");
|
|
StatusMessageTextWriter.WriteLine(new System.String('-', 72));
|
|
header = false;
|
|
}
|
|
if (Verbose)
|
|
{
|
|
StatusMessageTextWriter.WriteLine("{1,-22} {2,-8} {3,4:F0}% {4,-8} {0}",
|
|
e.FileName,
|
|
e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
|
|
e.UncompressedSize,
|
|
e.CompressionRatio,
|
|
e.CompressedSize);
|
|
if (!String.IsNullOrEmpty(e.Comment))
|
|
StatusMessageTextWriter.WriteLine(" Comment: {0}", e.Comment);
|
|
}
|
|
e.Password = _Password; // this may be null
|
|
OnExtractEntry(n, true, e, path);
|
|
if (overrideExtractExistingProperty)
|
|
e.ExtractExistingFile = this.ExtractExistingFile;
|
|
e.Extract(path);
|
|
n++;
|
|
OnExtractEntry(n, false, e, path);
|
|
if (_extractOperationCanceled)
|
|
break;
|
|
}
|
|
|
|
if (!_extractOperationCanceled)
|
|
{
|
|
// workitem 8264:
|
|
// now, set times on directory entries, again.
|
|
// The problem is, extracting a file changes the times on the parent
|
|
// directory. So after all files have been extracted, we have to
|
|
// run through the directories again.
|
|
foreach (ZipEntry e in _entries.Values)
|
|
{
|
|
// check if it is a directory
|
|
if ((e.IsDirectory) || (e.FileName.EndsWith("/")))
|
|
{
|
|
string outputFile = (e.FileName.StartsWith("/"))
|
|
? Path.Combine(path, e.FileName.Substring(1))
|
|
: Path.Combine(path, e.FileName);
|
|
|
|
e._SetTimes(outputFile, false);
|
|
}
|
|
}
|
|
OnExtractAllCompleted(path);
|
|
}
|
|
|
|
}
|
|
finally
|
|
{
|
|
|
|
_inExtractAll = false;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|