using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Runtime.Remoting; namespace Developpez.Dotnet.IO { /// /// Fournit des méthodes d'extension pour les flux /// public static class StreamExtensions { /// /// Copie le contenu d'un flux vers le flux spécifié /// /// le flux d'origine /// le flux de destination /// le nombre d'octets copiés public static int CopyToStream(this Stream fromStream, Stream toStream) { int totalBytes = 0; byte[] buffer = new byte[4096]; int nRead = 0; while ((nRead = fromStream.Read(buffer, 0, buffer.Length)) > 0) { toStream.Write(buffer, 0, nRead); totalBytes += nRead; } return totalBytes; } /// /// Copie le contenu d'un flux vers le fichier spécifié /// /// le flux d'origine /// le chemin du fichier de destination /// le nombre d'octets copiés public static int CopyToFile(this Stream fromStream, string path) { using (FileStream toStream = File.OpenWrite(path)) { return fromStream.CopyToStream(toStream); } } /// /// Renvoie un wrapper autour d'un flux, qui ignore les demandes de fermeture de façon à éviter la fermeture /// du flux lorsque le reader ou writer qui travaille dessus est fermé /// /// Le flux à wrapper /// Un wrapper non-fermable autour de ce flux public static Stream AsNonClosing(this Stream stream) { return new NonClosingStreamWrapper(stream); } /// /// Wraps a stream for all operations except Close and Dispose, which /// merely flush the stream and prevent further operations from being /// carried out using this wrapper. /// /// Cette classe provient de la librairie MiscUtil créée par Jon Skeet /// http://www.yoda.arachsys.com/csharp/miscutil/ /// /// private sealed class NonClosingStreamWrapper : Stream { #region Members specific to this wrapper class /// /// Creates a new instance of the class, wrapping the specified stream. /// /// The stream to wrap. Must not be null. /// stream is null public NonClosingStreamWrapper(Stream stream) { stream.CheckArgumentNull("stream"); this.stream = stream; } Stream stream; /// /// Stream wrapped by this wrapper /// public Stream BaseStream { get { return stream; } } /// /// Whether this stream has been closed or not /// bool closed = false; /// /// Throws an InvalidOperationException if the wrapper is closed. /// void CheckClosed() { if (closed) { throw new InvalidOperationException(ExceptionMessages.WrapperClosedOrDisposed); } } #endregion #region Overrides of Stream methods and properties /// /// Begins an asynchronous read operation. /// /// The buffer to read the data into. /// /// The byte offset in buffer at which to begin writing data read from the stream. /// /// The maximum number of bytes to read. /// /// An optional asynchronous callback, to be called when the read is complete. /// /// /// A user-provided object that distinguishes this particular /// asynchronous read request from other requests. /// /// /// An IAsyncResult that represents the asynchronous read, /// which could still be pending. /// public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { CheckClosed(); return stream.BeginRead(buffer, offset, count, callback, state); } /// /// Begins an asynchronous write operation. /// /// The buffer to write data from. /// The byte offset in buffer from which to begin writing. /// The maximum number of bytes to write. /// /// An optional asynchronous callback, to be called when the write is complete. /// /// /// A user-provided object that distinguishes this particular asynchronous /// write request from other requests. /// /// /// An IAsyncResult that represents the asynchronous write, /// which could still be pending. /// public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { CheckClosed(); return stream.BeginWrite(buffer, offset, count, callback, state); } /// /// Indicates whether or not the underlying stream can be read from. /// public override bool CanRead { get { return closed ? false : stream.CanRead; } } /// /// Indicates whether or not the underlying stream supports seeking. /// public override bool CanSeek { get { return closed ? false : stream.CanSeek; } } /// /// Indicates whether or not the underlying stream can be written to. /// public override bool CanWrite { get { return closed ? false : stream.CanWrite; } } /// /// This method is not proxied to the underlying stream; instead, the wrapper /// is marked as unusable for other (non-close/Dispose) operations. The underlying /// stream is flushed if the wrapper wasn't closed before this call. /// public override void Close() { if (!closed) { stream.Flush(); } closed = true; } /// /// Throws a NotSupportedException. /// /// The Type of the object that the new ObjRef will reference. /// n/a public override ObjRef CreateObjRef(Type requestedType) { throw new NotSupportedException(); } /// /// Waits for the pending asynchronous read to complete. /// /// /// The reference to the pending asynchronous request to finish. /// /// /// The number of bytes read from the stream, between zero (0) /// and the number of bytes you requested. Streams only return /// zero (0) at the end of the stream, otherwise, they should /// block until at least one byte is available. /// public override int EndRead(IAsyncResult asyncResult) { CheckClosed(); return stream.EndRead(asyncResult); } /// /// Ends an asynchronous write operation. /// /// A reference to the outstanding asynchronous I/O request. public override void EndWrite(IAsyncResult asyncResult) { CheckClosed(); stream.EndWrite(asyncResult); } /// /// Flushes the underlying stream. /// public override void Flush() { CheckClosed(); stream.Flush(); } /// /// Throws a NotSupportedException. /// /// n/a public override object InitializeLifetimeService() { throw new NotSupportedException(); } /// /// Returns the length of the underlying stream. /// public override long Length { get { CheckClosed(); return stream.Length; } } /// /// Gets or sets the current position in the underlying stream. /// public override long Position { get { CheckClosed(); return stream.Position; } set { CheckClosed(); stream.Position = value; } } /// /// Reads a sequence of bytes from the underlying stream and advances the /// position within the stream by the number of bytes read. /// /// /// An array of bytes. When this method returns, the buffer contains /// the specified byte array with the values between offset and /// (offset + count- 1) replaced by the bytes read from the underlying source. /// /// /// The zero-based byte offset in buffer at which to begin storing the data /// read from the underlying stream. /// /// /// The maximum number of bytes to be read from the /// underlying stream. /// /// The total number of bytes read into the buffer. /// This can be less than the number of bytes requested if that many /// bytes are not currently available, or zero (0) if the end of the /// stream has been reached. /// public override int Read(byte[] buffer, int offset, int count) { CheckClosed(); return stream.Read(buffer, offset, count); } /// /// Reads a byte from the stream and advances the position within the /// stream by one byte, or returns -1 if at the end of the stream. /// /// The unsigned byte cast to an Int32, or -1 if at the end of the stream. public override int ReadByte() { CheckClosed(); return stream.ReadByte(); } /// /// Sets the position within the current stream. /// /// A byte offset relative to the origin parameter. /// /// A value of type SeekOrigin indicating the reference /// point used to obtain the new position. /// /// The new position within the underlying stream. public override long Seek(long offset, SeekOrigin origin) { CheckClosed(); return stream.Seek(offset, origin); } /// /// Sets the length of the underlying stream. /// /// The desired length of the underlying stream in bytes. public override void SetLength(long value) { CheckClosed(); stream.SetLength(value); } /// /// Writes a sequence of bytes to the underlying stream and advances /// the current position within the stream by the number of bytes written. /// /// /// An array of bytes. This method copies count bytes /// from buffer to the underlying stream. /// /// /// The zero-based byte offset in buffer at /// which to begin copying bytes to the underlying stream. /// /// The number of bytes to be written to the underlying stream. public override void Write(byte[] buffer, int offset, int count) { CheckClosed(); stream.Write(buffer, offset, count); } /// /// Writes a byte to the current position in the stream and /// advances the position within the stream by one byte. /// /// The byte to write to the stream. public override void WriteByte(byte value) { CheckClosed(); stream.WriteByte(value); } #endregion } /// /// Renvoie une séquence d'octets lus à partir d'un flux. /// /// Flux à partir duquel lire les données /// Taille de buffer à utiliser pour la lecture /// La séquence d'octets lus à partir du flux public static IEnumerable AsByteEnumerable(this Stream stream, int bufferSize) { byte[] buffer = new byte[bufferSize]; int nRead = 0; while ((nRead = stream.Read(buffer, 0, bufferSize)) > 0) { for (int i = 0; i < nRead; i++) { yield return buffer[i]; } } } /// /// Renvoie une séquence d'octets lus à partir d'un flux. /// /// Flux à partir duquel lire les données /// La séquence d'octets lus à partir du flux public static IEnumerable AsByteEnumerable(this Stream stream) { return stream.AsByteEnumerable(4096); } /// /// Renvoie une séquence de blocs d'octets lus à partir d'un flux. /// /// Flux à partir duquel lire les données /// Taille de bloc désirée /// Une séquence de blocs d'octets de la taille spécifiée, lus à partir du flux ; le dernier bloc renvoyé peut être plus court si la fin du flux a été atteinte. public static IEnumerable AsBlockEnumerable(this Stream stream, int blockSize) { byte[] buffer = new byte[blockSize]; int nRead = 0; while ((nRead = stream.Read(buffer, 0, blockSize)) > 0) { byte[] buf2 = new byte[nRead]; Array.Copy(buffer, buf2, nRead); yield return buf2; } } } }