/// <summary> /// Opens a <see cref="LogReader"/> to read the content of a compressed or uncompressed stream. /// The stream will be closed when <see cref="LogReader.Dispose"/> will be called. /// </summary> /// <param name="seekableStream">Stream that must support Seek operations (<see cref="Stream.CanSeek"/> must be true).</param> /// <param name="dataOffset"> /// An optional offset where the stream position must be initially set: this is the position of an entry in the actual (potentially uncompressed stream), /// not the offset in the original stream. /// </param> /// <param name="filter">An optional <see cref="MulticastFilter"/>.</param> /// <returns>A <see cref="LogReader"/> that will close the file when disposed.</returns> /// <remarks> /// .ckmon files exist in different file versions, depending on headers. /// The file can be compressed using GZipStream, in which case the header will be the magic GZIP header: 1F 8B. /// New header (applies to version 5), the file will start with 43 4B 4D 4F 4E (CKMON in ASCII), followed by the version number, instead of only the version number. /// </remarks> public static LogReader Open(Stream seekableStream, long dataOffset = 0, MulticastFilter filter = null) { if (seekableStream == null) { throw new ArgumentNullException("seekableStream"); } if (!seekableStream.CanSeek) { throw new ArgumentException("Stream must support seek operations.", "seekableStream"); } LogReaderStreamInfo i = LogReaderStreamInfo.OpenStream(seekableStream); var s = i.LogStream; if (dataOffset > 0) { if (s.CanSeek) { s.Seek(dataOffset, SeekOrigin.Current); } else { var buffer = new byte[8192]; int toRead; while ((toRead = (int)Math.Min(8192, dataOffset)) > 0 && s.Read(buffer, 0, toRead) == toRead) { dataOffset -= toRead; } } } var r = new LogReader(s, i.Version, i.HeaderLength); r.CurrentFilter = filter; return(r); }
/// <summary> /// Opens a <see cref="LogReader"/> to read the content of a compressed or uncompressed file. /// The file will be closed when <see cref="LogReader.Dispose"/> will be called. /// </summary> /// <param name="path">Path of the log file.</param> /// <param name="dataOffset"> /// An optional offset where the stream position must be initially set: this is the position of an entry in the actual (potentially uncompressed stream), /// not the offset in the original stream. /// </param> /// <param name="filter">An optional <see cref="MulticastFilter"/>.</param> /// <returns>A <see cref="LogReader"/> that will close the file when disposed.</returns> /// <remarks> /// .ckmon files exist in different file versions, depending on headers. /// The file can be compressed using GZipStream, in which case the header will be the magic GZIP header: 1F 8B. /// New header (applies to version 5), the file will start with 43 4B 4D 4F 4E (CKMON in ASCII), followed by the version number, instead of only the version number. /// </remarks> public static LogReader Open(string path, long dataOffset = 0, MulticastFilter filter = null) { if (path == null) { throw new ArgumentNullException("path"); } FileStream fs = null; try { fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 8192, FileOptions.SequentialScan); return(Open(fs, dataOffset, filter)); } catch { if (fs != null) { fs.Dispose(); } throw; } }