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;
}
}
}
}