Beispiel #1
0
 protected virtual void CloseStreams()
 {
     if (ReadStream != null)
     {
         ReadStream.Close();
     }
     if (WriteStream != null)
     {
         WriteStream.Close();
     }
 }
Beispiel #2
0
        public void Clear()
        {
            WriteStream.Close();
            HStream.Close();
            File.Delete(HPath);

            HStream     = new FileStream(HPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            ReadOffset  = 0;
            WriteStream = new StreamWriter(HStream, Encoding.UTF8, 256, true);
            HBuffer.Clear();
        }
Beispiel #3
0
            public void OpenStream()
            {
                if (WriteStream != null)
                {
                    WriteStream.Flush();
                    WriteStream.Close();
                    WriteStream.Dispose();
                    WriteStream = null;
                }

                WriteStream = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None);
                TimeStarted = Environment.TickCount;
            }
Beispiel #4
0
            public void OpenStream()
            {
                if (WriteStream != null)
                {
                    WriteStream.Flush();
                    WriteStream.Close();
                    WriteStream.Dispose();
                    WriteStream = null;
                }

                WriteStream = File.Open(FilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                TimeStarted = Environment.TickCount;
            }
Beispiel #5
0
 public override void Close()
 {
     if (!leaveOpen)
     {
         try
         {
             WriteStream.Close();
         }
         finally
         {
             ReadStream.Close();
         }
     }
 }
        public virtual void Close()
        {
            ActionUtils.IgnoreExceptions(Flush);

            ActionUtils.IgnoreExceptions(() => WriteStream.Close());

            ActionUtils.IgnoreExceptions(() => Socket.Close());

            if (!closeFired)
            {
                closeFired = true;

                OnClosed(EventArgs.Empty);
            }
        }
Beispiel #7
0
            protected virtual void Dispose(bool disposing)
            {
                if (disposed)
                {
                    return;
                }

                if (disposing)
                {
                    if (WriteStream != null)
                    {
                        WriteStream.Flush();
                        WriteStream.Close();
                        WriteStream.Dispose();
                        WriteStream = null;
                    }
                }
                disposed = true;
            }
Beispiel #8
0
 protected override void Dispose(bool disposing)
 {
     if (disposing)
     {
         closedCancelSource.Cancel();
         if (!leaveOpen)
         {
             if (WriteStream != null)
             {
                 WriteStream.Close();
             }
             if (ReadStream != null)
             {
                 ReadStream.Close();
             }
         }
     }
     base.Dispose(disposing);
 }
Beispiel #9
0
 public async Task CloseAsync(CancellationToken cancel_token)
 {
     if (!closedCancelSource.IsCancellationRequested)
     {
         writeBuffer.CloseWrite();
         readBuffer.CloseRead();
         try {
             await Task.WhenAll(writeTask, readTask).ConfigureAwait(false);
         }
         catch (Exception) {
         }
         closedCancelSource.Cancel();
         if (WriteStream != null)
         {
             WriteStream.Close();
         }
         if (ReadStream != null)
         {
             ReadStream.Close();
         }
     }
     Close();
 }
Beispiel #10
0
 protected override void Dispose(bool disposing)
 {
     if (disposing && !closedCancelSource.IsCancellationRequested)
     {
         writeBuffer.CloseWrite();
         readBuffer.CloseRead();
         try {
             Task.WhenAll(writeTask, readTask).Wait();
         }
         catch (AggregateException) {
         }
         closedCancelSource.Cancel();
         if (WriteStream != null)
         {
             WriteStream.Close();
         }
         if (ReadStream != null)
         {
             ReadStream.Close();
         }
         closedCancelSource.Dispose();
     }
     base.Dispose(disposing);
 }
        /// <summary>
        ///   Saves the Zip archive to a file, specified by the Name property of the
        ///   <c>ZipFile</c>.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   The <c>ZipFile</c> instance is written to storage, typically a zip file
        ///   in a filesystem, only when the caller calls <c>Save</c>.  In the typical
        ///   case, the Save operation writes the zip content to a temporary file, and
        ///   then renames the temporary file to the desired name. If necessary, this
        ///   method will delete a pre-existing file before the rename.
        /// </para>
        ///
        /// <para>
        ///   The <see cref="ZipFile.Name"/> property is specified either explicitly,
        ///   or implicitly using one of the parameterized ZipFile constructors.  For
        ///   COM Automation clients, the <c>Name</c> property must be set explicitly,
        ///   because COM Automation clients cannot call parameterized constructors.
        /// </para>
        ///
        /// <para>
        ///   When using a filesystem file for the Zip output, it is possible to call
        ///   <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each
        ///   call the zip content is re-written to the same output file.
        /// </para>
        ///
        /// <para>
        ///   Data for entries that have been added to the <c>ZipFile</c> instance is
        ///   written to the output when the <c>Save</c> method is called. This means
        ///   that the input streams for those entries must be available at the time
        ///   the application calls <c>Save</c>.  If, for example, the application
        ///   adds entries with <c>AddEntry</c> using a dynamically-allocated
        ///   <c>MemoryStream</c>, the memory stream must not have been disposed
        ///   before the call to <c>Save</c>. See the <see
        ///   cref="ZipEntry.InputStream"/> property for more discussion of the
        ///   availability requirements of the input stream for an entry, and an
        ///   approach for providing just-in-time stream lifecycle management.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/>
        ///
        /// <exception cref="Ionic.Zip.BadStateException">
        ///   Thrown if you haven't specified a location or stream for saving the zip,
        ///   either in the constructor or by setting the Name property, or if you try
        ///   to save a regular zip archive to a filename with a .exe extension.
        /// </exception>
        ///
        /// <exception cref="System.OverflowException">
        ///   Thrown if <see cref="MaxOutputSegmentSize"/> is non-zero, and the number
        ///   of segments that would be generated for the spanned zip file during the
        ///   save operation exceeds 99.  If this happens, you need to increase the
        ///   segment size.
        /// </exception>
        ///
        public void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled             = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                {
                    throw new BadStateException("You haven't specified where to save the zip.");
                }

                if (_name != null && _name.EndsWith(".exe") && !_SavingSfx)
                {
                    throw new BadStateException("You specified an EXE for a plain zip file.");
                }

                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose)
                    {
                        StatusMessageTextWriter.WriteLine("No save is necessary....");
                    }
                    return;
                }

                Reset(true);

                if (Verbose)
                {
                    StatusMessageTextWriter.WriteLine("saving....");
                }

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                {
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");
                }


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c) // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                    {
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                    }
                }



                if (_saveOperationCanceled)
                {
                    return;
                }

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss != null)
                    ? zss.CurrentSegment
                    : 1;

                bool directoryNeededZip64 =
                    ZipOutput.WriteCentralDirectoryStructure
                        (WriteStream,
                        c,
                        _numberOfSegmentsForMostRecentSave,
                        _zip64,
                        Comment,
                        new ZipContainer(this));

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved    = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64   = new Nullable <bool>(thisSaveUsedZip64);

                if (_fileAlreadyExists && this._readstream != null)
                {
                    // This means we opened and read a zip file.
                    // If we are now saving, we need to close the orig file, first.
                    this._readstream.Close();
                    this._readstream = null;
                }
                // the archiveStream for each entry needs to be null
                foreach (var e in c)
                {
                    var zss1 = e._archiveStream as ZipSegmentedStream;
                    if (zss1 != null)
#if NETCF
                    { zss1.Close(); }
#else
                    { zss1.Dispose(); }
#endif
                    e._archiveStream = null;
                }

                // do the rename as necessary
                if (_name != null &&
                    (_temporaryFileName != null || zss != null))
                {
                    // _temporaryFileName may remain null if we are writing to a stream.
                    // only close the stream if there is a file behind it.
#if NETCF
                    WriteStream.Close();
#else
                    WriteStream.Dispose();
#endif

                    if (_saveOperationCanceled)
                    {
                        return;
                    }

                    string tmpName = null;
                    if (File.Exists(_name))
                    {
                        // the steps:
                        //
                        // 1. Delete tmpName
                        // 2. move existing zip to tmpName
                        // 3. rename (File.Move) working file to name of existing zip
                        // 4. delete tmpName
                        //
                        // This series of steps avoids the exception,
                        // System.IO.IOException:
                        //   "Cannot create a file when that file already exists."
                        //
                        // Cannot just call File.Replace() here because
                        // there is a possibility that the TEMP volume is different
                        // that the volume for the final file (c:\ vs d:\).
                        // So we need to do a Delete+Move pair.
                        //
                        // But, when doing the delete, Windows allows a process to
                        // delete the file, even though it is held open by, say, a
                        // virus scanner. It gets internally marked as "delete
                        // pending". The file does not actually get removed from the
                        // file system, it is still there after the File.Delete
                        // call.
                        //
                        // Therefore, we need to move the existing zip, which may be
                        // held open, to some other name. Then rename our working
                        // file to the desired name, then delete (possibly delete
                        // pending) the "other name".
                        //
                        // Ideally this would be transactional. It's possible that the
                        // delete succeeds and the move fails. Lacking transactions, if
                        // this kind of failure happens, we're hosed, and this logic will
                        // throw on the next File.Move().
                        //
                        //File.Delete(_name);
                        // workitem 10447
#if NETCF || SILVERLIGHT
                        tmpName = _name + "." + SharedUtilities.GenerateRandomStringImpl(8, 0) + ".tmp";
#else
                        tmpName = _name + "." + Path.GetRandomFileName();
#endif
                        if (File.Exists(tmpName))
                        {
                            DeleteFileWithRetry(tmpName);
                        }
                        File.Move(_name, tmpName);
                    }

                    OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive);
                    File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName,
                              _name);

                    OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive);

                    if (tmpName != null)
                    {
                        try
                        {
                            // not critical
                            if (File.Exists(tmpName))
                            {
                                File.Delete(tmpName);
                            }
                        }
                        catch
                        {
                            // don't care about exceptions here.
                        }
                    }
                    _fileAlreadyExists = true;
                }
                _readName = _name;

                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }
Beispiel #12
0
        /// <summary>
        /// Saves the Zip archive to a file, specified by the Name property of the <c>ZipFile</c>.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        /// The <c>ZipFile</c> instance is written to storage, typically a zip file in a
        /// filesystem, only when the caller calls <c>Save</c>.  The Save operation writes
        /// the zip content to a temporary file, and then renames the temporary file
        /// to the desired name. If necessary, this method will delete a pre-existing file
        /// before the rename.
        /// </para>
        ///
        /// <para> The <see cref="ZipFile.Name"/> property is specified either
        /// explicitly, or implicitly using one of the parameterized ZipFile
        /// constructors.  For COM Automation clients, the <c>Name</c> property must be
        /// set explicitly, because COM Automation clients cannot call parameterized
        /// constructors.  </para>
        ///
        /// <para>
        /// When using a filesystem file for the Zip output, it is possible to call
        /// <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each call the zip
        /// content is re-written to the same output file.
        /// </para>
        ///
        /// <para>
        /// Data for entries that have been added to the <c>ZipFile</c> instance is written
        /// to the output when the <c>Save</c> method is called. This means that the input
        /// streams for those entries must be available at the time the application calls
        /// <c>Save</c>.  If, for example, the application adds entries with <c>AddEntry</c>
        /// using a dynamically-allocated <c>MemoryStream</c>, the memory stream must not
        /// have been disposed before the call to <c>Save</c>. See the <see
        /// cref="ZipEntry.InputStream"/> property for more discussion of the availability
        /// requirements of the input stream for an entry, and an approach for providing
        /// just-in-time stream lifecycle management.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/>
        ///
        /// <exception cref="Ionic.Zip.BadStateException">
        /// Thrown if you haven't specified a location or stream for saving the zip,
        /// either in the constructor or by setting the Name property, or if you try to
        /// save a regular zip archive to a filename with a .exe extension.
        /// </exception>
        ///
        public void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled             = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                {
                    throw new BadStateException("You haven't specified where to save the zip.");
                }

                if (_name != null && _name.EndsWith(".exe") && !_SavingSfx)
                {
                    throw new BadStateException("You specified an EXE for a plain zip file.");
                }

                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose)
                    {
                        StatusMessageTextWriter.WriteLine("No save is necessary....");
                    }
                    return;
                }

                Reset();

                if (Verbose)
                {
                    StatusMessageTextWriter.WriteLine("saving....");
                }

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                {
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");
                }


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c)     // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                    {
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                    }
                }



                if (_saveOperationCanceled)
                {
                    return;
                }

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss != null)
                    ? zss.CurrentSegment
                    : 1;

                bool directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure(WriteStream,
                                                                                     c,
                                                                                     _numberOfSegmentsForMostRecentSave,
                                                                                     _zip64,
                                                                                     Comment,
                                                                                     ProvisionalAlternateEncoding);

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved    = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64   = new Nullable <bool>(thisSaveUsedZip64);


                // do the rename as necessary
                if (_name != null &&
                    (_temporaryFileName != null || zss != null))
                {
                    // _temporaryFileName may remain null if we are writing to a stream.
                    // only close the stream if there is a file behind it.
                    WriteStream.Close();
#if !NETCF
                    WriteStream.Dispose();
#endif
                    if (_saveOperationCanceled)
                    {
                        return;
                    }

                    if ((_fileAlreadyExists) && (this._readstream != null))
                    {
                        // This means we opened and read a zip file.
                        // If we are now saving to the same file, we need to close the
                        // orig file, first.
                        this._readstream.Close();
                        this._readstream = null;
                        // the archiveStream for each entry needs to be null
                        foreach (var e in c)
                        {
                            e._archiveStream = null;
                        }
                    }

                    if (_fileAlreadyExists)
                    {
                        // We do not just call File.Replace() here because
                        // there is a possibility that the TEMP volume is different
                        // that the volume for the final file (c:\ vs d:\).
                        // So we need to do a Delete+Move pair.
                        //
                        // Ideally this would be transactional.
                        //
                        // It's possible that the delete succeeds and the move fails.
                        // in that case, we're hosed, and we'll throw.
                        //
                        // Could make this more complicated by moving (renaming) the first file, then
                        // moving the second, then deleting the first file. But the
                        // error handling and unwrap logic just gets more complicated.
                        //
                        // Better to just keep it simple.
                        File.Delete(_name);
                    }

                    OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive);
                    File.Move((zss != null) ? zss.CurrentName : _temporaryFileName, _name);
                    OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive);

                    _fileAlreadyExists = true;
                }

                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }
Beispiel #13
0
        /// <summary>
        ///   Saves the Zip archive to a file, specified by the Name property of the
        ///   <c>ZipFile</c>.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   The <c>ZipFile</c> instance is written to storage, typically a zip file
        ///   in a filesystem, only when the caller calls <c>Save</c>.  In the typical
        ///   case, the Save operation writes the zip content to a temporary file, and
        ///   then renames the temporary file to the desired name. If necessary, this
        ///   method will delete a pre-existing file before the rename.
        /// </para>
        ///
        /// <para>
        ///   The <see cref="ZipFile.Name"/> property is specified either explicitly,
        ///   or implicitly using one of the parameterized ZipFile constructors.  For
        ///   COM Automation clients, the <c>Name</c> property must be set explicitly,
        ///   because COM Automation clients cannot call parameterized constructors.
        /// </para>
        ///
        /// <para>
        ///   When using a filesystem file for the Zip output, it is possible to call
        ///   <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each
        ///   call the zip content is re-written to the same output file.
        /// </para>
        ///
        /// <para>
        ///   Data for entries that have been added to the <c>ZipFile</c> instance is
        ///   written to the output when the <c>Save</c> method is called. This means
        ///   that the input streams for those entries must be available at the time
        ///   the application calls <c>Save</c>.  If, for example, the application
        ///   adds entries with <c>AddEntry</c> using a dynamically-allocated
        ///   <c>MemoryStream</c>, the memory stream must not have been disposed
        ///   before the call to <c>Save</c>. See the <see
        ///   cref="ZipEntry.InputStream"/> property for more discussion of the
        ///   availability requirements of the input stream for an entry, and an
        ///   approach for providing just-in-time stream lifecycle management.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/>
        ///
        /// <exception cref="Ionic.Zip.BadStateException">
        ///   Thrown if you haven't specified a location or stream for saving the zip,
        ///   either in the constructor or by setting the Name property, or if you try
        ///   to save a regular zip archive to a filename with a .exe extension.
        /// </exception>
        ///
        /// <exception cref="System.OverflowException">
        ///   Thrown if <see cref="MaxOutputSegmentSize"/> is non-zero, and the number
        ///   of segments that would be generated for the spanned zip file during the
        ///   save operation exceeds 99.  If this happens, you need to increase the
        ///   segment size.
        /// </exception>
        ///
        public void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled             = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                {
                    throw new BadStateException("You haven't specified where to save the zip.");
                }

                if (_name != null && _name.EndsWith(".exe") && !_SavingSfx)
                {
                    throw new BadStateException("You specified an EXE for a plain zip file.");
                }

                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose)
                    {
                        StatusMessageTextWriter.WriteLine("No save is necessary....");
                    }
                    return;
                }

                Reset(true);

                if (Verbose)
                {
                    StatusMessageTextWriter.WriteLine("saving....");
                }

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                {
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");
                }


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c) // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                    {
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                    }
                }



                if (_saveOperationCanceled)
                {
                    return;
                }

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss != null)
                    ? zss.CurrentSegment
                    : 1;

                bool directoryNeededZip64 =
                    ZipOutput.WriteCentralDirectoryStructure
                        (WriteStream,
                        c,
                        _numberOfSegmentsForMostRecentSave,
                        _zip64,
                        Comment,
                        new ZipContainer(this));

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved    = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64   = new Nullable <bool>(thisSaveUsedZip64);


                // do the rename as necessary
                if (_name != null &&
                    (_temporaryFileName != null || zss != null))
                {
                    // _temporaryFileName may remain null if we are writing to a stream.
                    // only close the stream if there is a file behind it.
#if NETCF
                    WriteStream.Close();
#else
                    WriteStream.Dispose();
#endif
                    if (_saveOperationCanceled)
                    {
                        return;
                    }

                    if (_fileAlreadyExists && this._readstream != null)
                    {
                        // This means we opened and read a zip file.
                        // If we are now saving to the same file, we need to close the
                        // orig file, first.
                        this._readstream.Close();
                        this._readstream.Dispose();
                        this._readstream = null;
                        // the archiveStream for each entry needs to be null
                        foreach (var e in c)
                        {
                            var zss1 = e._archiveStream as ZipSegmentedStream;
                            if (zss1 != null)
#if NETCF
                            { zss1.Close(); }
#else
                            { zss1.Dispose(); }
#endif
                            e._archiveStream = null;
                        }
                    }

                    if (_fileAlreadyExists && this._writestream != null)
                    {
                        this.WriteStream.Close();
                    }

                    string tmpName = null;
                    if (File.Exists(_name))
                    {
                        // the steps:
                        //
                        // 1. Delete tmpName
                        // 2. move existing zip to tmpName
                        // 3. rename (File.Move) working file to name of existing zip
                        // 4. delete tmpName
                        //
                        // This series of steps avoids the exception,
                        // System.IO.IOException:
                        //   "Cannot create a file when that file already exists."
                        //
                        // Cannot just call File.Replace() here because
                        // there is a possibility that the TEMP volume is different
                        // that the volume for the final file (c:\ vs d:\).
                        // So we need to do a Delete+Move pair.
                        //
                        // But, when doing the delete, Windows allows a process to
                        // delete the file, even though it is held open by, say, a
                        // virus scanner. It gets internally marked as "delete
                        // pending". The file does not actually get removed from the
                        // file system, it is still there after the File.Delete
                        // call.
                        //
                        // Therefore, we need to move the existing zip, which may be
                        // held open, to some other name. Then rename our working
                        // file to the desired name, then delete (possibly delete
                        // pending) the "other name".
                        //
                        // Ideally this would be transactional. It's possible that the
                        // delete succeeds and the move fails. Lacking transactions, if
                        // this kind of failure happens, we're hosed, and this logic will
                        // throw on the next File.Move().
                        //
                        //File.Delete(_name);
                        // workitem 10447
#if NETCF || SILVERLIGHT
                        tmpName = _name + "." + SharedUtilities.GenerateRandomStringImpl(8, 0) + ".tmp";
#else
                        tmpName = _name + "." + Path.GetRandomFileName();
#endif
                        if (File.Exists(tmpName))
                        {
                            DeleteFileWithRetry(tmpName);
                        }

                        try {
                            File.Move(_name, tmpName);
                        }
                        catch {
                            if (System.Diagnostics.Debugger.IsAttached)
                            {
                                System.Diagnostics.Debugger.Break(); //Look at the comment below. Added this to force a break here instead of your catch so you don't miss the cause and waste your time like I did
                            }
                            throw;
                        }

                        //Oh boy. You've just hit an exception on that File.Move line right above this stating that the template file can't be renamed because it's open
                        //in another process, right?

                        //Congratulation! You've probably run into the same gibberish I ran into!

                        //Check to make sure your file streams are closed, and ITpipes/Template Editor/Winrar/7-Zip don't have the template file open. I'm betting you won't find anything.

                        //If you try closing Visual Studio and running the binary directly I'm betting you won't have this crash occur. Go ahead--try it.

                        //What the hell, right?

                        //The XAML designer process (XDesProc.exe) is configured, by default, to populate its ViewModel in the designer UI. This creates a copy of the model--which creates a second
                        //Ionic.Zip.ZipFile object using the same template file. So when *this* ZipFile object attempts to move the existing template to replace it with an updated file
                        //the exception is thrown.

                        //To fix this, disable the following option in the Visual Studio toolbar above:
                        // Tools -> Options -> XAML Designer -> "Run project code in XAML Designer (if supported)"

                        //Once that's disabled, restart Visual Studio. Problem solved.

                        //Hopefully these comments will prevent someone else from wasting their time obsessing over their streams and AntiVirus. - Vincent Nary
                    }

                    OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive);
                    File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName,
                              _name);

                    OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive);

                    if (tmpName != null)
                    {
                        try
                        {
                            // not critical
                            if (File.Exists(tmpName))
                            {
                                File.Delete(tmpName);
                            }
                        }
                        catch
                        {
                            // don't care about exceptions here.
                        }
                    }
                    _fileAlreadyExists = true;
                }

                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }
Beispiel #14
0
        byte[] ReadBuffer = new byte[1024 * 128 * 1]; // кеш - 0.5 Мб
        void DownloadFileStreamly(Stream dataStream)
        {
            DownloadProgress CurrentDownloadProgress = new DownloadProgress();
            Stream           WriteStream             = null;
            Exception        TempEx = null;

            try
            {
                if (Current.DownloadPathSave != null)
                {
                    string FilePath = Current.DownloadPathSave + "\\" + Current.Filename;

                    if (System.IO.File.Exists(FilePath))
                    {
                        System.IO.FileInfo xx = new System.IO.FileInfo(FilePath);
                        if (xx.Length > Current.FileSize)
                        {
                            xx.Delete();
                            Current.BytesDownloaded = 0;
                        }
                    }
                    else
                    {
                        Current.BytesDownloaded = 0;
                    }
                    WriteStream = new FileStream(FilePath, FileMode.OpenOrCreate);
                    CurrentDownloadProgress.FilePath = FilePath;
                }
                else
                {
                    WriteStream = Current.OutputData;
                }

                if (Current.FileSize == Current.BytesDownloaded && Current.BytesDownloaded != 0 &&
                    Current.FileDownloaded)
                {
                    throw new Exception("Файл уже закачан " + Current.FullURL);
                }

                if (Current.FileSize > 0 && Current.BytesDownloaded == 0 &&
                    WriteStream.Length != Current.FileSize)
                {   // если известен размер файла и файл только что добавили, то создаем пустышку в размер файла
                    WriteStream.SetLength(Current.FileSize);
                }

                if (WriteStream.Length == Current.BytesDownloaded && WriteStream.Length != 0)
                {
                    Current.BytesDownloaded = 0;
                }

                WriteStream.Position = Current.BytesDownloaded;

                DateTime BeginTime = DateTime.Now;
                TimeSpan TimeDifference;
                TimeSpan RemainTime;

                int    BeginDownloadBytes        = Current.BytesDownloaded;
                int    ReadData                  = 1;
                int    BufferOffset              = 0;
                double LastTimeDifferenceSeconds = 0;

                while (DownloadFileThreadRunning)
                {
                    if (!DownloadFileThreadPause)
                    { // если не была задана пауза
                        ReadData      = dataStream.Read(ReadBuffer, BufferOffset, ReadBuffer.Length - BufferOffset);
                        BufferOffset += ReadData;

                        TimeDifference = DateTime.Now - BeginTime;

                        if (((ReadBuffer.Length - BufferOffset) < 1024) ||              // осталось черезчур мало места в буффере
                            (ReadData == 0) ||                                          // закачка закончилась
                            (TimeDifference.TotalSeconds != LastTimeDifferenceSeconds)) // но не реже 1 раза в секунду
                        {
                            WriteStream.Write(ReadBuffer, 0, BufferOffset);
                            Current.BytesDownloaded += BufferOffset;

                            if (TimeDifference.TotalSeconds != LastTimeDifferenceSeconds)
                            {
                                CurrentDownloadProgress.DownloadSize = Math.Max(Current.BytesDownloaded, Current.FileSize);
                                CurrentDownloadProgress.Bytes        = Current.BytesDownloaded;
                                CurrentDownloadProgress.Speed        = (
                                    (Current.BytesDownloaded - BeginDownloadBytes) * 1000.0f
                                    / (float)TimeDifference.TotalMilliseconds);

                                RemainTime = new TimeSpan((long)
                                                          ((TimeDifference.Ticks * (Current.FileSize - Current.BytesDownloaded))
                                                           / (float)(Current.BytesDownloaded - BeginDownloadBytes))
                                                          );

                                CurrentDownloadProgress.RemainTime = RemainTime.ToString();

                                CurrentDownloadProgress.Type = DownloadMessageType.DownloadProgressShow;
                                SygnalEventProgress(CurrentDownloadProgress);

                                if (TimeDifference.TotalSeconds >= 5)
                                {
                                    BeginTime          = DateTime.Now;
                                    BeginDownloadBytes = Current.BytesDownloaded;
                                }
                            }
                            ;

                            BufferOffset = 0;
                            LastTimeDifferenceSeconds = TimeDifference.TotalSeconds;
                        }
                    }
                    else
                    {// была задана пауза
                        CurrentDownloadProgress.Type = DownloadMessageType.DownloadPaused;
                        SygnalEventProgress(CurrentDownloadProgress);
                        Thread.Sleep(500);
                    }

                    if (ReadData == 0)
                    {     // все закачали
                        if (Current.FileSize == -1)
                        { // не был известен размер файла
                            Current.FileSize = Current.BytesDownloaded;
                        }
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                TempEx = ex;
                //    ErrorWork(new Exception("Размер файла " + Current.FileSize));
            }
            finally
            {
                WriteStream.Close();

                // финальное состояние
                CurrentDownloadProgress.DownloadSize = Math.Max(Current.BytesDownloaded, Current.FileSize);
                CurrentDownloadProgress.Bytes        = Current.BytesDownloaded;
                CurrentDownloadProgress.Type         = DownloadMessageType.DownloadProgressShow;
                SygnalEventProgress(CurrentDownloadProgress);

                if (DownloadFileThreadRunning && Current.FileSize == Current.BytesDownloaded)
                {   // файл закончен
                    CurrentDownloadProgress.Type = DownloadMessageType.DownloadFinished;
                    SygnalEventProgress(CurrentDownloadProgress);
                    Current.FileDownloaded = true;
                }
                else
                { // была нажата кнопка стоп -поэтому - ничего не вызываем
                    CurrentDownloadProgress.Type           = DownloadMessageType.DownloadStopped;
                    CurrentDownloadProgress.AdditionalInfo = "DownloadFileThreadRunning " + DownloadFileThreadRunning.ToString() +
                                                             " Current.FileSize = " + Current.FileSize.ToString() +
                                                             " Current.BytesDownloaded = " + Current.BytesDownloaded.ToString();
                    SygnalEventProgress(CurrentDownloadProgress);
                }

                DownloadFileThreadRunning = false;
            }
            if (TempEx != null)
            {
                throw TempEx;
            }
        }