C# Extension methods for the Stream class.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Extensions
{
    public static class StreamExtensions
    {
        /// <summary>
        /// Read the contents of a Stream from its current location
        /// into a String
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static string ReadAllText(this Stream stream)
        {
            using (var reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }

        /// <summary>
        /// Read all the bytes in a Stream from its current
        /// location to a byte[] array
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static byte[] ReadAllBytes(this Stream stream)
        {
            using (var content = new MemoryStream())
            {
                var buffer = new byte[4096];

                int read = stream.Read(buffer, 0, 4096);
                while (read > 0)
                {
                    content.Write(buffer, 0, read);
                    read = stream.Read(buffer, 0, 4096);
                }

                return content.ToArray();
            }
        }

        /// <summary>
        /// Asynchronously read the contents of a Stream from its current location
        /// into a String
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static async Task<string> ReadAllTextAsync(this Stream stream)
        {
            string result;

            using (var reader = new StreamReader(stream))
            {
                result = await reader.ReadToEndAsync().ConfigureAwait(false);
            }

            return result;
        }

        /// <summary>
        /// Asynchronously read all the bytes in a Stream from its current
        /// location to a byte[] array
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static async Task<byte[]> ReadAllBytesAsync(this Stream stream)
        {
            using (var content = new MemoryStream())
            {
                var buffer = new byte[4096];

                int read = await stream.ReadAsync(buffer, 0, 4096).ConfigureAwait(false);
                while (read > 0)
                {
                    content.Write(buffer, 0, read);
                    read = await stream.ReadAsync(buffer, 0, 4096).ConfigureAwait(false);
                }

                return content.ToArray();
            }
        }

        public static async Task<List<string>> ReadLinesAsync(this Stream stream)
        {
            var lines = new List<string>();

            using (var reader = new StreamReader(stream))
            {
                string line;
                while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
                {
                    lines.Add(line);
                }
            }

            return lines;
        }

        public static Func<Stream> ToStreamFactory(this Stream stream)
        {
            byte[] buffer;
            using (var memoryStream = new MemoryStream())
            {
                try
                {
                    stream.CopyTo(memoryStream);
                    buffer = memoryStream.ToArray();
                }
                finally
                {
                    stream.Close();
                }
            }
            return () => (Stream)new MemoryStream(buffer);
        }

        public static Stream AsStream(this string value)
        {
            return value.AsStream(Encoding.UTF8);
        }

        public static Stream AsStream(this string value, Encoding encoding)
        {
            return new MemoryStream(encoding.GetBytes(value));
        }

        public static bool ContentEquals(this Stream stream, Stream otherStream)
        {
            bool flag = IsBinary(otherStream);

            otherStream.Seek(0L, SeekOrigin.Begin);

            if (!flag)
            {
                return CompareText(stream, otherStream);
            }

            return CompareBinary(stream, otherStream);
        }

        public static bool IsBinary(Stream stream)
        {
            byte[] numArray = new byte[30];
            int count = stream.Read(numArray, 0, 30);

            return Array.FindIndex(numArray, 0, count, d => d == 0) >= 0;
        }

        private static bool CompareText(Stream stream, Stream otherStream)
        {
            return ReadStreamLines(stream).SequenceEqual(ReadStreamLines(otherStream),
                StringComparer.Ordinal);
        }

        private static IEnumerable<string> ReadStreamLines(Stream stream)
        {
            using (var streamReader = new StreamReader(stream))
            {
                while (streamReader.Peek() != -1)
                {
                    string line = streamReader.ReadLine();
                    yield return line;
                }
            }
        }

        private static bool CompareBinary(Stream stream, Stream otherStream)
        {
            if (stream.CanSeek && otherStream.CanSeek
                && stream.Length != otherStream.Length)
            {
                return false;
            }

            byte[] buffer1 = new byte[4096];
            byte[] buffer2 = new byte[4096];

            int count;
            do
            {
                count = stream.Read(buffer1, 0, buffer1.Length);
                if (count > 0)
                {
                    int num = otherStream.Read(buffer2, 0, count);
                    if (count != num)
                    {
                        return false;
                    }
                    for (int index = 0; index < count; ++index)
                    {
                        if (buffer1[index] != buffer2[index])
                        {
                            return false;
                        }
                    }
                }
            }

            while (count > 0);

            return true;
        }
    }
}