using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text.RegularExpressions; namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities { /// /// Help methods for work with streams /// [ExcludeFromCodeCoverage] public static class StreamHelper { /// /// Convert stream to byte array /// /// Stream /// Byte array public static byte[] StreamToArray(Stream pStream) { long iLength = pStream.Length; var bytes = new byte[iLength]; for (int i = 0; i < iLength; i++) { bytes[i] = (byte)pStream.ReadByte(); } pStream.Close(); return bytes; } /// /// Convert byte array to stream /// /// Byte array /// Open stream /// public static Stream ArrayToStreamAppend(byte[] pBynaryArray, Stream pStream) { #region Check params if (ReferenceEquals(pBynaryArray, null)) { throw new ArgumentNullException(nameof(pBynaryArray)); } if (ReferenceEquals(pStream, null)) { throw new ArgumentNullException(nameof(pStream)); } if (!pStream.CanWrite) { throw new ArgumentException("Can't write to stream", nameof(pStream)); } #endregion Check params foreach (byte b in pBynaryArray) { pStream.WriteByte(b); } return pStream; } public static void StreamToStreamAppend(Stream streamIn, Stream streamToWrite) { StreamToStreamAppend(streamIn, streamToWrite, 0); } public static void StreamToStreamAppend(Stream streamIn, Stream streamToWrite, long dataLength) { #region Check params if (ReferenceEquals(streamIn, null)) { throw new ArgumentNullException(nameof(streamIn)); } if (ReferenceEquals(streamToWrite, null)) { throw new ArgumentNullException(nameof(streamToWrite)); } if (!streamIn.CanRead) { throw new ArgumentException("Can't read from stream", nameof(streamIn)); } if (!streamToWrite.CanWrite) { throw new ArgumentException("Can't write to stream", nameof(streamToWrite)); } #endregion Check params var buf = new byte[512]; long length; if (dataLength == 0) { length = streamIn.Length - streamIn.Position; } else { length = dataLength; } long rest = length; while (rest > 0) { int len1 = streamIn.Read(buf, 0, rest >= 512 ? 512 : (int)rest); streamToWrite.Write(buf, 0, len1); rest -= len1; } } /// /// Compare two streams by converting them to strings and comparing the strings /// /// /// /// /// /// public static bool Compare(Tuple tuple1, Tuple tuple2, bool stripColumnWidths) { #region Check if (tuple1 == null || tuple1.Item1 == null || tuple1.Item2 == null) { throw new ArgumentNullException(nameof(tuple1)); } if (tuple2 == null || tuple2.Item1 == null || tuple2.Item2 == null) { throw new ArgumentNullException(nameof(tuple2)); } if (tuple1.Item2.Position != 0) { throw new ArgumentException("Must be in position 0", nameof(tuple1)); } if (tuple2.Item2.Position != 0) { throw new ArgumentException("Must be in position 0", nameof(tuple2)); } #endregion Check var stringOne = new StreamReader(tuple1.Item2).ReadToEnd().RemoveIgnoredParts(tuple1.Item1, stripColumnWidths, ignoreGuids: true); var stringOther = new StreamReader(tuple2.Item2).ReadToEnd().RemoveIgnoredParts(tuple2.Item1, stripColumnWidths, ignoreGuids: true); return stringOne == stringOther; } private static string RemoveIgnoredParts(this string s, Uri uri, bool ignoreColumnWidths, bool ignoreGuids) { s = uriSpecificIgnores.Where(p => p.Key.Equals(uri.OriginalString)).Aggregate(s, (current, pair) => pair.Value.Replace(current, "")); // Collapse empty xml elements s = emptyXmlElementRegex.Replace(s, "<$1 />"); if (ignoreColumnWidths) s = RemoveColumnWidths(s); if (ignoreGuids) s = RemoveGuids(s); return s; } private static IEnumerable> uriSpecificIgnores = new List>() { // Remove dcterms elements new KeyValuePair("/docProps/core.xml", new Regex(@"", RegexOptions.Compiled)) }; private static Regex emptyXmlElementRegex = new Regex(@"<([\w:]+)><\/\1>", RegexOptions.Compiled); private static Regex columnRegex = new Regex("", RegexOptions.Compiled); private static Regex widthRegex = new Regex("width=\"\\d+(\\.\\d+)?\"\\s+", RegexOptions.Compiled); private static string RemoveColumnWidths(string s) { var replacements = new Dictionary(); foreach (var m in columnRegex.Matches(s).OfType()) { var original = m.Groups[0].Value; var replacement = widthRegex.Replace(original, ""); replacements.Add(original, replacement); } return replacements.Aggregate(s, (current, r) => current.Replace(r.Key, r.Value)); } private static Regex guidRegex = new Regex(@"{[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}}", RegexOptions.Compiled | RegexOptions.Multiline); private static string RemoveGuids(string s) => guidRegex.Replace(s, m => string.Empty); } }