/// <summary> /// Fills the specified table by reading data from a file or stream. /// </summary> public void Fill(DataTable dataTable) { if (dataTable == null) { throw new ArgumentNullException(nameof(dataTable)); } Stream stream; BinaryReader reader = null; try { stream = Stream ?? new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); reader = new BinaryReader(stream, Encoding.UTF8, Stream != null); // prepare the data table dataTable.Rows.Clear(); dataTable.BeginLoadData(); dataTable.DefaultView.Sort = ""; // create table columns if (dataTable.Columns.Count == 0) { dataTable.Columns.Add("DateTime", typeof(DateTime)); dataTable.Columns.Add("CnlNum", typeof(int)); dataTable.Columns.Add("Val", typeof(double)); dataTable.Columns.Add("Stat", typeof(int)); } // read header byte[] buffer = new byte[HeaderSize]; if (!ReadHeader(reader, buffer)) { return; } // read slices int[] cnlNums = null; while (true) { if (reader.ReadUInt16() != BlockMarker) { throw new ScadaException("Slice marker not found."); } DateTime timestamp = ScadaUtils.TicksToTime(reader.ReadInt64()); int cnlCnt = reader.ReadInt32(); if (cnlCnt != 0) { int cnlDataSize = cnlCnt * 10; int cnlNumsSize = cnlCnt * 4; ResizeBuffer(ref buffer, cnlDataSize); // read channel numbers if (cnlCnt > 0) { ReadData(reader, buffer, 0, cnlNumsSize + 4, true); cnlNums = new int[cnlCnt]; Buffer.BlockCopy(buffer, 0, cnlNums, 0, cnlNumsSize); if (ScadaUtils.CRC32(buffer, 0, cnlNumsSize) != BitConverter.ToUInt32(buffer, cnlNumsSize)) { throw new ScadaException("CRC error."); } } else if (cnlCnt < 0) // channel numbers are the same { cnlCnt = ~cnlCnt; if (cnlNums == null) { throw new ScadaException("Channel numbers are undefined."); } if (cnlNums.Length != cnlCnt) { throw new ScadaException("Invalid channel count."); } } // read channel data ReadData(reader, buffer, 0, cnlDataSize, true); for (int i = 0, index = 0; i < cnlCnt; i++) { DataRow row = dataTable.NewRow(); row["DateTime"] = timestamp; row["CnlNum"] = cnlNums[i]; row["Val"] = GetDouble(buffer, ref index); row["Stat"] = GetUInt16(buffer, ref index); dataTable.Rows.Add(row); } } } } catch (EndOfStreamException) { // normal file ending case } finally { reader?.Close(); dataTable.EndLoadData(); dataTable.AcceptChanges(); if (dataTable.Columns.Count > 0) { dataTable.DefaultView.Sort = "DateTime, CnlNum"; } } }
/// <summary> /// Reads a single slice from a file or stream. /// </summary> public Slice ReadSingleSlice() { Stream stream; BinaryReader reader = null; try { stream = Stream ?? new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); reader = new BinaryReader(stream, Encoding.UTF8, Stream != null); // read header byte[] buffer = new byte[HeaderSize]; if (!ReadHeader(reader, buffer)) { return(null); } // read the first slice if (reader.ReadUInt16() != BlockMarker) { throw new ScadaException("Slice marker not found."); } DateTime timestamp = ScadaUtils.TicksToTime(reader.ReadInt64()); int cnlCnt = reader.ReadInt32(); if (cnlCnt > 0) { // read channel numbers int cnlDataSize = cnlCnt * 10; int cnlNumsSize = cnlCnt * 4; buffer = new byte[cnlDataSize]; ReadData(reader, buffer, 0, cnlNumsSize + 4, true); int[] cnlNums = new int[cnlCnt]; Buffer.BlockCopy(buffer, 0, cnlNums, 0, cnlNumsSize); if (ScadaUtils.CRC32(buffer, 0, cnlNumsSize) != BitConverter.ToUInt32(buffer, cnlNumsSize)) { throw new ScadaException("CRC error."); } // read channel data ReadData(reader, buffer, 0, cnlDataSize, true); CnlData[] cnlData = new CnlData[cnlCnt]; for (int i = 0, index = 0; i < cnlCnt; i++) { cnlData[i] = GetCnlData(buffer, ref index); } return(new Slice(timestamp, cnlNums, cnlData)); } else if (cnlCnt == 0) { return(new Slice(timestamp, 0)); } else { throw new ScadaException("Invalid channel count."); } } catch (EndOfStreamException) { // unable to read slice return(null); } finally { reader?.Close(); } }