public static bool TryParse(byte[] line, out CompressedLog log) { log = null; if (NumberHandler.TryParseNumber(line, 0, out ulong deltaDateTime, out var indexEndDeltaTime)) { if (NumberHandler.TryParseNumber(line, indexEndDeltaTime + 2, out ulong deltaRunTime, out var indexEndDeltaRunTime)) { if (line[indexEndDeltaTime + 1] == ' ' && line[indexEndDeltaRunTime + 1] == ' ' && line[indexEndDeltaRunTime + 5 + 2] == ' ') { var message = new byte[line.Length - (indexEndDeltaRunTime + 2)]; Array.Copy(line, indexEndDeltaRunTime + 2, message, 0, line.Length - (indexEndDeltaRunTime + 2)); log = new CompressedLog(deltaDateTime, deltaRunTime, message); return(true); } } } return(false); }
//здесь реализована логика алгоритма //Сжатие: //первая строка в нужном формате опорная, относительно нее все считается и она просто переписывается как есть //затем берется две соседних строки, если текущая строка больше или равна предыдущей, берется разность дат и времени работы //и записывается в новую строку, если же нет, то текущая строка считается опорной, //строки которые не подходят под формат лога, просто переписываются как есть //Разжатие: //В целом аналогично сжатию, но в обратную сторону, из двух строк одна уже была переведена в исходное состояние или она опорная //к ней прибавляется разница дат и времени работы записанная в следующей строке public static void Convert(Stream source, Stream target, ConvertMode mode) { Log previous = null; var isFirstLine = true; foreach (var line in Splitter.ReadLines(source)) { if (isFirstLine) { if (Log.TryParse(line, out var current)) { Connector.Write(target, current.ToBytes()); previous = current; isFirstLine = false; } else { Connector.Write(target, line); } } else { if (mode == ConvertMode.Convert) { Convert(line); } else { Deconvert(line); } } } Connector.Write(target, new byte[0]); void Convert(byte[] line) { if (Log.TryParse(line, out var current)) { if ((current.DateTime >= previous.DateTime) && (current.RunTime >= previous.RunTime)) { var currentCompressed = new CompressedLog((current.DateTime - previous.DateTime).TotalMilliseconds, (current.RunTime - previous.RunTime), current.Message); Connector.Write(target, currentCompressed.ToBytes()); } else { Connector.Write(target, current.ToBytes()); } previous = current; } else { Connector.Write(target, line); } } void Deconvert(byte[] line) { if (CompressedLog.TryParse(line, out var currentCompressed)) { var currentUncompressed = new Log(previous.DateTime.AddMilliseconds(currentCompressed.DeltaDateTime), previous.RunTime + currentCompressed.DeltaRunTime, currentCompressed.Message); Connector.Write(target, currentUncompressed.ToBytes()); previous = currentUncompressed; } else { if (Log.TryParse(line, out var current)) { previous = current; } Connector.Write(target, line); } } }