Feedback

C# - Stream, der mit foreach() durchlaufen werden kann

Veröffentlicht von am 31.10.2009
(2 Bewertungen)
Dies ist ein Stream-Wrapper mit dem man einen Basisstream mit einer foreach()-Schleife durchlaufen kann. Beispiel:


System.IO.Stream datei = System.IO.File.OpenRead(@"D:\datei_tm.png");

// Stream erstellen mit einer Puffergrösse von 10240 Bytes, den Stream beim "Disposen" ebenfalls schliessen
using (stream = new EnumerableStream(datei, 10240, true))
{
foreach (byte[] daten in stream)
{
Console.WriteLine(daten.Length);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;

namespace MarcelJKloubert.IO
{
    /// <summary>
    /// Ein Stream, der durchlaufen werden kann
    /// </summary>
    public sealed class EnumerableStream : Stream, IEnumerable<byte[]>
    {
        #region CLASS: StreamEnumerator
        private class StreamEnumerator : IEnumerator<byte[]>
        {
            #region Felder
            private byte[] _current = null;
            private StreamEnumerable _parent = null;
            #endregion


            #region Konstruktoren
            public StreamEnumerator(StreamEnumerable parent)
            {
                if (null == parent)
                {
                    throw new ArgumentNullException("parent");
                }

                this._parent = parent;
            }
            #endregion


            #region Eigenschaften
            /// <summary>
            /// 
            /// </summary>
            /// <see cref="System.Collections.Generic.IEnumerator&lt;T&gt;.Current"/>
            public byte[] Current
            {
	            get { return this._current; }
            }

            /// <summary>
            /// 
            /// </summary>
            /// <see cref="System.Collections.IEnumerator.Current"/>
            object IEnumerator.Current
            {
	            get { return this.Current; }
            }

            /// <summary>
            /// Gibt die Vaterinstanz zurück
            /// </summary>
            public StreamEnumerable Parent
            {
                get { return this._parent; }
            }
            #endregion

            #region Methoden
            /// <summary>
            /// 
            /// </summary>
            /// <see cref="System.IDisposable.Dispose"/>
            public void Dispose()
            { }

            /// <summary>
            /// 
            /// </summary>
            /// <see cref="System.Collections.Generic.IEnumerator&lt;T&gt;.MoveNext"/>
            public bool MoveNext()
            {
                byte[] buffer = new byte[this.Parent.BufferSize];

                int iBytesRead = this.Parent.Read(buffer, 0, buffer.Length);
                if (iBytesRead > 0)
                {
                    byte[] data = new byte[iBytesRead];
                    Array.Copy(buffer, data, iBytesRead);

                    this._current = data;
                }

                return iBytesRead > 0;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <see cref="System.Collections.Generic.IEnumerator&lt;T&gt;.Reset"/>
            public void Reset()
            {
                if (this.Parent.CanSeek)
                {
                    this.Parent.Position = 0;
                }

                this._current = null;
            }
            #endregion
        }
        #endregion


        #region Felder
        private Stream _baseStream   = null;
        private int _bufferSize      = 0;
        private bool _closeOnDispose = false;
        #endregion


        #region Konstruktoren
        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseStream">Basisstream</param>
        public StreamEnumerable(Stream baseStream) : this(baseStream, 4096)
        { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseStream">Basisstream</param>
        public StreamEnumerable(Stream baseStream, int bufferSize) : this(baseStream, bufferSize, false)
        { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseStream">Basisstream</param>
        /// <param name="closeAfterDispose">Speicher von Basisstream ebenfalls freigeben bei einem Dispose() (true) oder nicht (false)</param>
        public StreamEnumerable(Stream baseStream, bool closeOnDispose) : this(baseStream, 4096, closeOnDispose)
        { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseStream">Basisstream</param>
        /// <param name="bufferSize">Puffergrösse</param>
        /// <param name="closeAfterDispose">Speicher von Basisstream ebenfalls freigeben bei einem Dispose() (true) oder nicht (false)</param>
        public StreamEnumerable(Stream baseStream, int bufferSize, bool closeOnDispose)
        {
            if (null == baseStream)
            {
                throw new ArgumentNullException("baseStream");
            }

            if (bufferSize < 1)
            {
                throw new ArgumentOutOfRangeException("bufferSize");
            }

            this._baseStream = baseStream;
            this._bufferSize = bufferSize;
            this._closeOnDispose = closeOnDispose;
        }
        #endregion

        #region Eigenschaften
        /// <summary>
        /// Gibt den Basisstream zurück
        /// </summary>
        public Stream BaseStream
        {
            get { return this._baseStream; }
        }

        /// <summary>
        /// Gibt die Puffergrösse zurück
        /// </summary>
        public int BufferSize
        {
            get { return this._bufferSize; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.CanRead"/>
        public override bool CanRead
        {
            get { return this.BaseStream.CanRead; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.CanSeek"/>
        public override bool CanSeek
        {
            get { return this.BaseStream.CanSeek; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.CanWrite"/>
        public override bool CanWrite
        {
            get { return this.BaseStream.CanWrite; }
        }

        /// <summary>
        /// Gibt zurück, ob der Speicher des Basisstream ebenfalls bei einem Dispose() freigegeben wird (true) oder nicht (false)
        /// </summary>
        public bool CloseOnDispose
        {
            get { return this._closeOnDispose; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.Length"/>
        public override long Length
        {
            get { return this.BaseStream.Length; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.Position"/>
        public override long Position
        {
            get { return this.BaseStream.Position; }
            
            set { this.BaseStream.Position = value; }
        }
        #endregion

        #region Methoden
        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.Dispose"/>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.CloseOnDispose)
                {
                    this.BaseStream.Dispose();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.Flush"/>
        public override void Flush()
        {
            this.BaseStream.Flush();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.Collections.Generic.IEnumerable&lt;T&gt;.GetEnumerator"/>
        public IEnumerator<byte[]> GetEnumerator()
        {
            return new StreamEnumerator(this);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.Collections.IEnumerable.GetEnumerator"/>
        IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.Read"/>
        public override int Read(byte[] buffer, int offset, int count)
        {
            return this.BaseStream.Read(buffer, offset, count);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.Seek"/>
        public override long Seek(long offset, SeekOrigin origin)
        {
            return this.BaseStream.Seek(offset, origin);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.SetLength"/>
        public override void SetLength(long value)
        {
            this.BaseStream.SetLength(value);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <see cref="System.IO.Stream.Write"/>
        public override void Write(byte[] buffer, int offset, int count)
        {
            this.BaseStream.Write(buffer, offset, count);
        }
        #endregion
    }
}

4 Kommentare zum Snippet

Sperneder Patrick schrieb am 08.11.2009:
Sehr elegant ! Von mir dafür eine glatte 10.
Marcel Kloubert schrieb am 10.11.2009:
Besten Dank! :-)

Kleinen Schönheitsfehler hat der Code, hab ich grad gesehen: Die Konstruktoren sind falsch genamt. Die müssen "EnumerableStream" statt "StreamEnumerable" (so hies die Klasse vorher!). Ich kanns leider wieder nicht ändern ... wieder ein Serverfehler beim Versuch den Code zu ändern ... einer der Gründe warum ich lieber Webseiten in PHP programmiere ;-)
Marcel Kloubert schrieb am 10.11.2009:
selbes gilt im übrigen für den Paramater des Konstruktors von StreamEnumerator...
Marcel Kloubert schrieb am 10.11.2009:
und den rest in StreamEnumerator...
 

Logge dich ein, um hier zu kommentieren!