streamingZipPartStream.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Packaging / streamingZipPartStream.cs / 1305600 / streamingZipPartStream.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2005
//
//  File:           StreamingZipPartStream.cs 
//
//  Description:    The class StreamingZipPartStream is used to create a sequence of 
//                  piece streams in order to implement streaming production of packages. 
//
//  History:        05/15/05 - johnlarc - Initial implementation. 
//-----------------------------------------------------------------------------

using System;
using System.IO; 
using System.IO.Packaging;                  // For ZipPackagePart, etc.
using MS.Internal.IO.Zip;                   // For ZipFileInfo. 
using System.Windows;                       // for ExceptionStringTable 

using MS.Internal;                          // for Invariant 
using MS.Internal.WindowsBase;

namespace MS.Internal.IO.Packaging
{ 
    /// 
 	/// The class StreamingZipPartStream is used to create a sequence of 
    /// piece streams in order to implement streaming production of packages. 
    /// 
    ///  
    /// This class is defined for the benefit of ZipPackage, ZipPackagePart and
    /// InternalRelationshipCollection.
    /// Although it is quite specialized, it would hardly make sense to nest its definition in any
    /// of these clases. 
    /// 
    internal class StreamingZipPartStream : Stream 
    { 
        #region Constructors
 
        //-----------------------------------------------------
        //
        //  Constructors
        // 
        //-----------------------------------------------------
 
       ///  
        /// Build a System.IO.Stream to create a multi-piece (i.e. interleaved) part.
        /// Does not require a part, but a proper part name (not a piece name), and a ZipArchive. 
        /// 
        internal StreamingZipPartStream(
            string          partName,
            ZipArchive      zipArchive, 
            CompressionMethodEnum compressionMethod,
            DeflateOptionEnum deflateOption, 
            FileMode        mode, 
            FileAccess      access)
        { 
            // Right now, only production is supported in streaming mode.
            if (!(   (mode == FileMode.Create || mode == FileMode.CreateNew)
                  && access == FileAccess.Write) )
            { 
                throw new NotSupportedException(SR.Get(SRID.OnlyStreamingProductionIsSupported));
            } 
 
            _partName = partName;
            _archive = zipArchive; 
            _compressionMethod = compressionMethod;
            _deflateOption = deflateOption;
            _mode = mode;
            _access = access; 
        }
 
        #endregion Constructors 

        //------------------------------------------------------ 
        //
        //  Public Methods
        //
        //----------------------------------------------------- 

        ///  
        /// Return the bytes requested. 
        /// 
        /// Destination buffer. 
        /// 
        /// The zero-based byte offset in buffer at which to begin storing the data read
        /// from the current stream.
        ///  
        /// How many bytes requested.
        /// How many bytes were written into buffer. 
        public override int Read(byte[] buffer, int offset, int count) 
        {
            throw new NotSupportedException(SR.Get(SRID.OnlyWriteOperationsAreSupportedInStreamingCreation)); 
        }

        /// 
        /// Seek 
        /// 
        /// Offset in byte. 
        /// Offset origin (start, current, or end). 
        public override long Seek(long offset, SeekOrigin origin)
        { 
            throw new NotSupportedException(SR.Get(SRID.OnlyWriteOperationsAreSupportedInStreamingCreation));
        }

        ///  
        /// SetLength
        ///  
        public override void SetLength(long newLength) 
        {
            throw new InvalidOperationException(SR.Get(SRID.OperationViolatesWriteOnceSemantics, "SetLength")); 
        }

        /// 
        /// Write. Delegate to the current piece stream. 
        /// Lazily create the Zip item since we do not know what name to create it
        /// under until a write or a close occurs. 
        ///  
        public override void Write(byte[] buffer, int offset, int count)
        { 
            CheckClosed();

            // We now know we're creating a non-empty piece, so it's OK to give
            // it a non-terminal name. 
            EnsurePieceStream(false /* not last piece */);
            _pieceStream.Write(buffer, offset, count); 
        } 

        ///  
        /// Close the current piece stream and increment the piece number
        /// to allow on-demand creation of the next piece stream in Write
        /// or Close.
        ///  
        /// Pass through the Flush calls because there is no need to
        /// generate a new Piece if we are writing to a single, enormouse stream. 
        public override void Flush() 
        {
            CheckClosed(); 

            // _pieceStream will be null if there's been no write since the last flush.
            if (_pieceStream != null)
            { 
                // If CanWrite is false, we know that our underlying stream was closed by ZipIO layer
                // as a part of its logic.  Therefore, we need a new Piece. 
                if (_pieceStream.CanWrite) 
                    _pieceStream.Flush();
            } 
        }

        //------------------------------------------------------
        // 
        //  Public Properties
        // 
        //------------------------------------------------------ 

        #region Public Properties 

        /// 
        /// Is stream readable?
        ///  
        /// 
        /// Here, the assumption, as in all capability tests, is that the status of 
        /// the current piece reflects the status of all pieces for the part. 
        /// This is justified by the fact that (i) all piece streams are opened with the same
        /// parameters against the same archive and (ii) the current piece stream cannot get 
        /// closed unless the whole part stream is closed.
        /// 
        public override bool CanRead
        { 
            get
            { 
                return false; 
            }
        } 

        /// 
        /// Is stream seekable?
        ///  
        /// 
        /// Here, the assumption, as in all capability tests, is that the status of 
        /// the current piece reflects the status of all pieces for the part. 
        /// This is justified by the fact that (i) all piece streams are opened with the same
        /// parameters against the same archive and (ii) the current piece stream cannot get 
        /// closed unless the whole part stream is closed.
        /// 
        public override bool CanSeek
        { 
            get
            { 
                return false; 
            }
        } 

        /// 
        /// Is stream writable?
        ///  
        /// 
        /// Here, the assumption, as in all capability tests, is that the status of 
        /// the current piece reflects the status of all pieces for the part. 
        /// This is justified by the fact that (i) all piece streams are opened with the same
        /// parameters against the same archive and (ii) the current piece stream cannot get 
        /// closed unless the whole part stream is closed.
        /// 
        public override bool CanWrite
        { 
            get
            { 
                return !_closed; 
            }
        } 

        /// 
        /// Logical byte position in this stream.
        ///  
        public override long Position
        { 
            get 
            {
                return -1; 
            }
            set
            {
                throw new InvalidOperationException(SR.Get(SRID.OperationViolatesWriteOnceSemantics, "set_Position")); 
            }
        } 
 
        /// 
        /// Length. 
        /// 
        public override long Length
        {
            get 
            {
                return -1; 
            } 
        }
 
        #endregion Public Properties

        //-----------------------------------------------------
        // 
        //  Protected Methods
        // 
        //------------------------------------------------------ 

        #region Protected Methods 

        /// 
        /// Dispose(bool)
        ///  
        /// 
        ///  
        /// An instance of streams' peculiar dispose pattern, whereby 
        /// the inherited abstract Stream class implements Close by calling
        /// this virtual protected function. 
        /// In turn, each implementation is responsible for calling back
        /// its base's implementation.
        /// 
        protected override void Dispose(bool disposing) 
        {
            try 
            { 
                if (disposing)
                { 
                    if (!_closed)
                    {
                        // Flush pending changes into a piece, if any.
                        Flush(); 

                        // Create an empty last piece. 
                        EnsurePieceStream(true /* last piece */); 
                        _pieceStream.Close();
                    } 
                }
            }
            finally
            { 
                _closed = true;
                base.Dispose(disposing); 
            } 
        }
 
        #endregion Protected Methods

        //-----------------------------------------------------
        // 
        //   Private Methods
        // 
        //----------------------------------------------------- 

        private void EnsurePieceStream(bool isLastPiece) 
        {
            if (_pieceStream != null)
            {
                // Normally, the pieces are actually closed automatically for us by the 
                // underlying ZipIO logic, but in the case of the last piece (when we
                // are called by our own Dispose(bool) method) we must close it explicitly. 
                if (isLastPiece) 
                    _pieceStream.Close();
 
                // We detect that the stream has been closed by inspecting the CanWrite property
                // since this is guaranteed not to throw even when the stream is disposed.
                if (!_pieceStream.CanWrite)
                { 
                    // increment our piece number so we can generate the correct
                    // one below 
                    checked { ++_currentPieceNumber; } 

                    // release it to trigger the new piece creation below 
                    _pieceStream = null;
                }
            }
 
            if (_pieceStream == null)
            { 
                string pieceName = PieceNameHelper.CreatePieceName( 
                    _partName,
                    _currentPieceNumber, 
                    isLastPiece);
                string pieceZipName = ZipPackage.GetZipItemNameFromOpcName(pieceName);

                ZipFileInfo zipFileInfo = _archive.AddFile(pieceZipName, _compressionMethod, _deflateOption); 
                // We've just created the file, so the mode can only be Create, not CreateNew.
                // (At least, this is part of ZipFileInfo's belief system.) 
                _pieceStream = zipFileInfo.GetStream(FileMode.Create, _access); 
            }
        } 

        private void CheckClosed()
        {
            if (_closed) 
                throw new ObjectDisposedException(null, SR.Get(SRID.StreamObjectDisposed));
        } 
 
        //-----------------------------------------------------
        // 
        //   Private Properties
        //
        //------------------------------------------------------
        // None 

        #region Private Fields 
 
        //-----------------------------------------------------
        // 
        //  Private Fields
        //
        //------------------------------------------------------
 
        private Stream              _pieceStream;               // write-only stream on the current piece
        private string              _partName;                  // part name used to generate correct piece names 
        private ZipArchive          _archive; 
        private int                 _currentPieceNumber = 0;    // incremented with each piece Close() cycle
        private CompressionMethodEnum _compressionMethod; 
        private DeflateOptionEnum   _deflateOption;
        private FileMode            _mode;
        private FileAccess          _access;
        private bool                _closed = false; 

        #endregion Private Fields 
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK