using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;
namespace GMWare.IO
{
///
/// Provides some commonly used methods for Stream manipulation.
///
public static class StreamUtils
{
///
/// Opens a DeflateStream for reading Zlib compressed data from the current position of the parameter. Closing this Stream will not close the underlying Stream.
///
/// The Stream to create a DeflateStream from.
/// The opened DeflateStream.
public static DeflateStream OpenDeflateDecompressionStreamCheap(Stream stream)
{
return OpenDeflateDecompressionStreamCheap(stream, true);
}
///
/// Opens a DeflateStream for reading Zlib compressed data from the current position of the parameter.
///
/// The Stream to create a DeflateStream from.
/// Specifies whether or not the underlying Stream will be left open when this Stream is closed.
/// The opened DeflateStream.
public static DeflateStream OpenDeflateDecompressionStreamCheap(Stream stream, bool leaveOpen)
{
if (stream == null) throw new ArgumentNullException("stream");
stream.ReadByte();
stream.ReadByte();
return new DeflateStream(stream, CompressionMode.Decompress, leaveOpen);
}
///
/// Copies a number of bytes from one Stream to the other. The current position of each is used.
///
/// The Stream to copy from.
/// The Stream to copy to.
/// The number of bytes to copy.
/// Whether or not all requested bytes are copied.
[Obsolete("For backward compatibility only. Please use StreamCopy().")]
public static bool StreamCopyWithLength(Stream src, Stream dest, int length)
{
return StreamCopy(src, dest, length);
}
///
/// Copies a number of bytes from one Stream to the other. The current position of each is used.
///
/// The Stream to copy from.
/// The Stream to copy to.
/// The number of bytes to copy.
/// Whether or not all requested bytes are copied.
public static bool StreamCopy(Stream src, Stream dest, long length)
{
return StreamCopy(src, dest, length, null);
}
///
/// Copies a number of bytes from one Stream to the other. The current position of each is used.
///
/// The Stream to copy from.
/// The Stream to copy to.
/// The number of bytes to copy.
/// A delegate to process the read buffer before it's written to the destination.
/// Whether or not all requested bytes are copied.
public static bool StreamCopy(Stream src, Stream dest, long length, StreamCopyProcessor procDelegate)
{
if (src == null) throw new ArgumentNullException("src");
if (dest == null) throw new ArgumentNullException("dest");
if (length == 0) return true;
const int BUFFER_SIZE = 4096;
byte[] buffer = new byte[BUFFER_SIZE];
int read;
long left = length;
bool continueProcessing = true;
while (continueProcessing && left / buffer.Length != 0 && (read = src.Read(buffer, 0, buffer.Length)) > 0)
{
if (procDelegate != null)
{
continueProcessing = procDelegate(buffer, read);
}
dest.Write(buffer, 0, read);
left -= read;
}
// Should stop if zero bytes have been read from stream although some should have been read
if (length > BUFFER_SIZE && left == length) return false;
if (src.CanSeek && src.Position == src.Length && left != 0) throw new EndOfStreamException();
while (continueProcessing && left > 0 && (read = src.Read(buffer, 0, (int)left)) > 0)
{
if (procDelegate != null)
{
continueProcessing = procDelegate(buffer, read);
}
dest.Write(buffer, 0, read);
left -= read;
}
return left == 0;
}
///
/// Copies one Stream to the other. The current position of each is used.
///
/// The Stream to copy from.
/// The Stream to copy to.
/// The number of bytes copied.
public static long StreamCopy(Stream src, Stream dest)
{
return StreamCopy(src, dest, null);
}
///
/// Copies one Stream to the other. The current position of each is used.
///
/// The Stream to copy from.
/// The Stream to copy to.
/// A delegate for processing a read chunk before it is written.
/// The number of bytes copied.
public static long StreamCopy(Stream src, Stream dest, StreamCopyProcessor procDelegate)
{
if (src == null) throw new ArgumentNullException("src");
if (dest == null) throw new ArgumentNullException("dest");
// From Stack Overflow, probably
const int BUFFER_SIZE = 4096;
byte[] buffer = new byte[BUFFER_SIZE];
long bytesCopied = 0;
int bytesRead;
bool continueProcessing = true;
do
{
bytesRead = src.Read(buffer, 0, BUFFER_SIZE);
if (procDelegate != null)
{
continueProcessing = procDelegate(buffer, bytesRead);
}
dest.Write(buffer, 0, bytesRead);
bytesCopied += bytesRead;
}
while (continueProcessing && bytesRead != 0);
return bytesCopied;
}
///
/// Encapsulates a method for processing bytes that are being copied.
///
/// The bytes that have been read from the source stream and will be written to the destination stream
/// The number of bytes that have been read from the source stream stored in
///
public delegate bool StreamCopyProcessor(byte[] buffer, int bytesRead);
}
}