/// <summary> /// /// </summary> /// <param name="datafile"></param> /// <param name="offset"></param> /// <param name="tagCount"></param> /// <param name="fileDuration"></param> /// <param name="blockDuration"></param> /// <param name="timetick"></param> /// <param name="blockPointer"></param> /// <param name="time"></param> public static void ReadRegionHead(DataFileSeriserbase datafile, long offset, out int tagCount, out int fileDuration, out int blockDuration, out int timetick, out long blockPointer, out DateTime time) { //文件头部结构:Pre DataRegion(8) + Next DataRegion(8) + Datatime(8)+tagcount(4)+ tagid sum(8) +file duration(4)+ block duration(4)+Time tick duration(4)+ { + tagid1+tagid2+...+tagidn }+ {[tag1 block point1(8) + tag2 block point1+ tag3 block point1+...] + [tag1 block point2(8) + tag2 block point2+ tag3 block point2+...]....} var dataoffset = offset + 16; //读取时间 time = datafile.ReadDateTime(dataoffset); dataoffset += 8; //读取单个文件的时长 fileDuration = datafile.ReadInt(dataoffset); dataoffset += 4; //读取数据块时长 blockDuration = datafile.ReadInt(dataoffset); dataoffset += 4; //读取时钟周期 timetick = datafile.ReadInt(dataoffset); dataoffset += 4; //读取变量个数 tagCount = datafile.ReadInt(dataoffset); dataoffset += 4; blockPointer = dataoffset - offset; }
/// <summary> /// /// </summary> /// <param name="tid"></param> /// <returns></returns> private static long ReadTagIndex(this DataFileSeriserbase datafile, int tid, out long offset, out short len) { len = datafile.ReadShort(0); var vsize = datafile.ReadInt(2); offset = vsize; lock (TagHeadOffsetManager.manager.LogHeadOffsets) { if (!TagHeadOffsetManager.manager.Contains(datafile.FileName)) { var data = datafile.Read(6, vsize); MarshalVarintCodeMemory vcm = new MarshalVarintCodeMemory(data.StartMemory, vsize); var ltmp = vcm.ToLongList(); int addroffset = (ltmp.Count - 1) / 2; List <int> ids = new List <int>(); List <long> addrs = new List <long>(); long lp = ltmp[1]; for (int i = 1; i < ltmp[0]; i++) { var lp2 = ltmp[i + 1] + lp; ids.Add((int)lp2); lp = lp2; } lp = ltmp[1 + addroffset]; for (int i = 1; i < ltmp[0]; i++) { var lp2 = ltmp[i + 1 + addroffset] + lp; addrs.Add(lp2); lp = lp2; } Dictionary <int, long> idaddrs = new Dictionary <int, long>(); for (int i = 0; i < ids.Count; i++) { idaddrs.Add(ids[i], addrs[i]); } TagHeadOffsetManager.manager.AddLogHead(datafile.FileName, idaddrs); if (idaddrs.ContainsKey(tid)) { return(idaddrs[tid]); } } else { var idaddrs = TagHeadOffsetManager.manager.Get(datafile.FileName); if (idaddrs.ContainsKey(tid)) { return(idaddrs[tid]); } } } return(-1); }
///// <summary> ///// ///// </summary> //static Dictionary<string, MarshalMemoryBlock> mMemoryCach = new Dictionary<string, MarshalMemoryBlock>(); /// <summary> /// /// </summary> /// <param name="datafile"></param> /// <param name="address"></param> /// <returns></returns> private static MarshalMemoryBlock GetDataMemory(DataFileSeriserbase datafile, long address) { //说明数据没有采用Zip压缩,可以直接读取使用 var dp = address; var datasize = datafile.ReadInt(dp); return(datafile.Read(dp + 4, datasize)); }
/// <summary> /// /// </summary> /// <param name="tid"></param> /// <returns></returns> private static AddressAndSize ReadTagIndex(this DataFileSeriserbase datafile, int tid, out long offset, out short len) { len = datafile.ReadShort(0); //读取时长 var vsize = datafile.ReadInt(10); offset = vsize + 6; if (vsize > 7) { lock (TagHeadOffsetManager.manager.LogHeadOffsets) { if (!TagHeadOffsetManager.manager.Contains(datafile.FileName)) { Dictionary <int, AddressAndSize> dtmps = new Dictionary <int, AddressAndSize>(); var idandaddress = datafile.Read(14, vsize); int id = idandaddress.ReadInt(0); long address = idandaddress.ReadLong(4); int size = 0; long ltmp; int nid = 0; for (int i = 1; i < vsize / 12; i++) { nid = idandaddress.ReadInt(i * 12); ltmp = idandaddress.ReadLong(i * 12 + 4); size = (int)(ltmp - address); dtmps.Add(id, new AddressAndSize() { Address = address, Size = size }); address = ltmp; id = nid; } dtmps.Add(id, new AddressAndSize() { Address = address, Size = (int)(datafile.Length - address) }); TagHeadOffsetManager.manager.AddLogHead(datafile.FileName, dtmps); if (dtmps.ContainsKey(tid)) { return(dtmps[tid]); } } else { var idaddrs = TagHeadOffsetManager.manager.GetLog(datafile.FileName); if (idaddrs.ContainsKey(tid)) { return(idaddrs[tid]); } } } } return(AddressAndSize.Empty); }
/// <summary> /// /// </summary> /// <param name="datafile"></param> /// <param name="address"></param> private unsafe MarshalMemoryBlock ReadAndDecompressMemory(DataFileSeriserbase datafile, long address) { var vsize = datafile.ReadInt(address); var dsize = datafile.ReadInt(address + 4); var datas = datafile.Read(address + 8, vsize); int dtmp = 0; MarshalMemoryBlock mmb = new MarshalMemoryBlock(dsize, dsize); System.IO.Compression.BrotliDecoder.TryDecompress(new ReadOnlySpan <byte>((void *)datas.Handles[0], vsize), new Span <byte>((void *)mmb.Handles[0], dsize), out dtmp); if (dtmp != dsize) { LoggerService.Service.Warn("DataFileInfo", "解压缩数据长度不一致!" + datafile.FileName); } datas.Dispose(); return(mmb); }
///// <summary> ///// ///// </summary> //static Dictionary<string, MarshalMemoryBlock> mMemoryCach = new Dictionary<string, MarshalMemoryBlock>(); /// <summary> /// /// </summary> /// <param name="datafile"></param> /// <param name="address"></param> /// <returns></returns> private static MarshalMemoryBlock GetDataMemory(DataFileSeriserbase datafile, long address, int datapointer) { if (datapointer < 0) { //说明数据没有采用Zip压缩,可以直接读取使用 var dp = address + (datapointer & 0x7FFFFFFF); var datasize = datafile.ReadInt(dp); return(datafile.Read(dp + 4, datasize)); } else { return(DecodeMemoryCachManager.Manager.GetMemory(datafile, address, datapointer)); } }
/// <summary> /// /// </summary> /// <param name="datafile"></param> /// <param name="tid"></param> /// <param name="offset"></param> /// <param name="dataTime"></param> /// <param name="timetick"></param> /// <returns></returns> private static MarshalMemoryBlock ReadTagDataBlock(DataFileSeriserbase datafile, int tid, long offset, DateTime dataTime, out int timetick, out int index) { int fileDuration, blockDuration = 0; int tagCount = 0; DateTime time; long blockpointer = 0; var dindex = ReadTagIndexInDataPointer(datafile, tid, offset, out tagCount, out fileDuration, out blockDuration, out timetick, out blockpointer, out time); int blockcount = fileDuration * 60 / blockDuration; var startTime = datafile.ReadDateTime(16); var ttmp = (dataTime - startTime).TotalMinutes; int blockIndex = (int)(ttmp / blockDuration); if (ttmp % blockDuration > 0) { blockIndex++; } if (blockIndex > blockcount) { throw new Exception("DataPointer index is out of total block number"); } index = blockIndex; var headdata = datafile.Read(offset + blockpointer + dindex * blockcount * 12, blockcount * 12); var dataPointer = headdata.ReadInt(blockIndex * 12); //读取DataBlock的相对地址 var dataPointerbase = headdata.ReadLong(blockIndex * 12 + 4); //读取DataBlock的基地址 headdata.Dispose(); if (dataPointer >= 0) { return(GetDataMemory(datafile, dataPointerbase, dataPointer)); } else { var dp = dataPointerbase + (dataPointer & 0x7FFFFFFF); var datasize = datafile.ReadInt(dp); return(datafile.Read(dp + 4, datasize)); } }
/// <summary> /// /// </summary> /// <param name="datafile"></param> /// <param name="tid"></param> /// <param name="offset"></param> /// <param name="index"></param> /// <returns></returns> private static MarshalMemoryBlock ReadTagDataBlock(DataFileSeriserbase datafile, int tid, long offset, int index, out int timetick) { int fileDuration, blockDuration = 0; int tagCount = 0; DateTime time; long blockpointer = 0; var dindex = ReadTagIndexInDataPointer(datafile, tid, offset, out tagCount, out fileDuration, out blockDuration, out timetick, out blockpointer, out time); int blockIndex = index; int blockcount = fileDuration * 60 / blockDuration; //var headdata = GetHeadBlock(datafile, offset + blockpointer, tagCount * blockcount * 12); //var dataPointer = headdata.ReadInt(dindex * 12 + blockIndex * tagCount * 12); //读取DataBlock的相对地址 //var dataPointerbase = headdata.ReadLong(dindex * 12 + blockIndex * tagCount * 12 + 4); //读取DataBlock的基地址 var headdata = datafile.Read(offset + blockpointer + dindex * blockcount * 12, blockcount * 12); var dataPointer = headdata.ReadInt(blockIndex * 12); //读取DataBlock的相对地址 var dataPointerbase = headdata.ReadLong(blockIndex * 12 + 4); //读取DataBlock的基地址 headdata.Dispose(); if (dataPointerbase > 0) { if (dataPointer >= 0) { return(GetDataMemory(datafile, dataPointerbase, dataPointer)); } else { var dp = dataPointerbase + (dataPointer & 0x7FFFFFFF); var datasize = datafile.ReadInt(dp); return(datafile.Read(dp + 4, datasize)); } } else { return(null); } }
/// <summary> /// 检测数据头部指针区域数据是否被缓存 /// </summary> /// <param name="datafile"></param> /// <param name="offset"></param> /// <param name="fileDuration"></param> /// <param name="blockDuration"></param> /// <param name="timetick"></param> /// <returns></returns> public static Dictionary <int, int> CheckBlockHeadCach(this DataFileSeriserbase datafile, long offset, out int tagCount, out int fileDuration, out int blockDuration, out int timetick, out long blockPointer, out DateTime time) { //文件头部结构:Pre DataRegion(8) + Next DataRegion(8) + Datatime(8)+tagcount(4)+ tagid sum(8) +file duration(4)+ block duration(4)+Time tick duration(4)+ { + tagid1+tagid2+...+tagidn }+ {[tag1 block point1(8) + tag2 block point1+ tag3 block point1+...] + [tag1 block point2(8) + tag2 block point2+ tag3 block point2+...]....} var dataoffset = offset + 16; //读取时间 time = datafile.ReadDateTime(dataoffset); dataoffset += 8; //读取变量个数 int count = datafile.ReadInt(dataoffset); dataoffset += 4; tagCount = count; //读取校验和 long idsum = datafile.ReadLong(dataoffset); dataoffset += 8; //读取单个文件的时长 fileDuration = datafile.ReadInt(dataoffset); dataoffset += 4; //读取数据块时长 blockDuration = datafile.ReadInt(dataoffset); dataoffset += 4; //读取时钟周期 timetick = datafile.ReadInt(dataoffset); dataoffset += 4; lock (TagHeadOffsetManager.manager) { if (!TagHeadOffsetManager.manager.Contains(idsum, count)) { //Tag id 列表经过压缩,内容格式为:DataSize + Data var dsize = datafile.ReadInt(dataoffset); if (dsize <= 0) { tagCount = 0; fileDuration = 0; blockDuration = 0; timetick = 0; blockPointer = 0; return(new Dictionary <int, int>()); } dataoffset += 4; blockPointer = dataoffset + dsize - offset; var dtmp = new Dictionary <int, int>(); using (var dd = datafile.Read(dataoffset, dsize)) { MarshalVarintCodeMemory vcm = new MarshalVarintCodeMemory(dd.StartMemory, dsize); var ltmp = vcm.ToIntList(); //vcm.Dispose(); if (ltmp.Count > 0) { int preid = ltmp[0]; dtmp.Add(preid, 0); for (int i = 1; i < ltmp.Count; i++) { var id = ltmp[i] + preid; dtmp.Add(id, i); preid = id; } } TagHeadOffsetManager.manager.Add(idsum, count, dtmp, blockPointer); dd.Dispose(); } return(dtmp); } else { var re = TagHeadOffsetManager.manager.Get(idsum, count); blockPointer = re.Item2; return(re.Item1); } } }
/// <summary> /// /// </summary> /// <param name="datafile"></param> /// <param name="valIndex"></param> /// <param name="offset"></param> /// <param name="valueaddr"></param> /// <param name="result"></param> private static List <object> ReadValueInner <T>(this DataFileSeriserbase datafile, List <int> valIndex, long offset, long valueaddr, out int datasize) { List <object> re = new List <object>(); string tname = typeof(T).Name; switch (tname) { case "Boolean": foreach (var vv in valIndex) { re.Add(Convert.ToBoolean(datafile.ReadByte(offset + valueaddr + vv))); } datasize = 1; break; case "Byte": foreach (var vv in valIndex) { re.Add(datafile.ReadByte(offset + valueaddr + vv)); } datasize = 1; break; case "Int16": foreach (var vv in valIndex) { re.Add(datafile.ReadShort(offset + valueaddr + vv * 2)); } datasize = 2; break; case "UInt16": foreach (var vv in valIndex) { re.Add((ushort)datafile.ReadShort(offset + valueaddr + vv * 2)); } datasize = 2; break; case "Int32": foreach (var vv in valIndex) { re.Add(datafile.ReadInt(offset + valueaddr + vv * 4)); } datasize = 4; break; case "UInt32": foreach (var vv in valIndex) { re.Add((uint)datafile.ReadInt(offset + valueaddr + vv * 4)); } datasize = 4; break; case "Int64": foreach (var vv in valIndex) { re.Add((long)datafile.ReadLong(offset + valueaddr + vv * 8)); } datasize = 8; break; case "UInt64": foreach (var vv in valIndex) { re.Add((ulong)datafile.ReadLong(offset + valueaddr + vv * 8)); } datasize = 8; break; case "Double": foreach (var vv in valIndex) { re.Add(datafile.ReadDouble(offset + valueaddr + vv * 8)); } datasize = 8; break; case "Single": foreach (var vv in valIndex) { re.Add(datafile.ReadFloat(offset + valueaddr + vv * 4)); } datasize = 4; break; case "String": foreach (var vv in valIndex) { var str = Encoding.Unicode.GetString(datafile.ReadBytes(offset + valueaddr + vv * Const.StringSize, Const.StringSize)); re.Add(str); } datasize = Const.StringSize; break; case "DateTime": foreach (var vv in valIndex) { re.Add(datafile.ReadDateTime(offset + valueaddr + vv * 8)); } datasize = 8; break; case "IntPointData": foreach (var vv in valIndex) { var x = datafile.ReadInt(offset + valueaddr + vv * 8); var y = datafile.ReadInt(offset + valueaddr + vv * 8 + 4); re.Add(new IntPointData() { X = x, Y = y }); } datasize = 8; break; case "UIntPointData": foreach (var vv in valIndex) { var x = (uint)datafile.ReadInt(offset + valueaddr + vv * 8); var y = (uint)datafile.ReadInt(offset + valueaddr + vv * 8 + 4); re.Add(new UIntPointData() { X = x, Y = y }); } datasize = 8; break; case "LongPointData": foreach (var vv in valIndex) { var x = (long)datafile.ReadLong(offset + valueaddr + vv * 16); var y = (long)datafile.ReadLong(offset + valueaddr + vv * 16 + 8); re.Add(new LongPointData() { X = x, Y = y }); } datasize = 16; break; case "ULongPointData": foreach (var vv in valIndex) { var x = (ulong)datafile.ReadLong(offset + valueaddr + vv * 16); var y = (ulong)datafile.ReadLong(offset + valueaddr + vv * 16 + 8); re.Add(new ULongPointData() { X = x, Y = y }); } datasize = 16; break; case "IntPoint3Data": foreach (var vv in valIndex) { var x = datafile.ReadInt(offset + valueaddr + vv * 12); var y = datafile.ReadInt(offset + valueaddr + vv * 12 + 4); var z = datafile.ReadInt(offset + valueaddr + vv * 12 + 8); re.Add(new IntPoint3Data() { X = x, Y = y, Z = z }); } datasize = 12; break; case "UIntPoint3Data": foreach (var vv in valIndex) { var x = (uint)datafile.ReadInt(offset + valueaddr + vv * 12); var y = (uint)datafile.ReadInt(offset + valueaddr + vv * 12 + 4); var z = (uint)datafile.ReadInt(offset + valueaddr + vv * 12 + 8); re.Add(new UIntPoint3Data() { X = x, Y = y, Z = z }); } datasize = 12; break; case "LongPoint3Data": foreach (var vv in valIndex) { var x = (long)datafile.ReadLong(offset + valueaddr + vv * 24); var y = (long)datafile.ReadLong(offset + valueaddr + vv * 24 + 8); var z = (long)datafile.ReadLong(offset + valueaddr + vv * 24 + 168); re.Add(new LongPoint3Data() { X = x, Y = y, Z = z }); } datasize = 24; break; case "ULongPoint3Data": foreach (var vv in valIndex) { var x = (ulong)datafile.ReadLong(offset + valueaddr + vv * 24); var y = (ulong)datafile.ReadLong(offset + valueaddr + vv * 24 + 8); var z = (ulong)datafile.ReadLong(offset + valueaddr + vv * 24 + 168); re.Add(new ULongPoint3Data() { X = x, Y = y, Z = z }); } datasize = 24; break; default: datasize = 0; break; } return(re); }
/// <summary> /// /// </summary> /// <param name="datafile"></param> /// <param name="valIndex"></param> /// <param name="offset"></param> /// <param name="valueaddr"></param> /// <param name="result"></param> private static List <object> ReadValueInner <T>(this DataFileSeriserbase datafile, List <int> valIndex, long offset, long valueaddr, out int datasize) { List <object> re = new List <object>(); if (typeof(T) == typeof(bool)) { foreach (var vv in valIndex) { re.Add(Convert.ToBoolean(datafile.ReadByte(offset + valueaddr + vv))); } datasize = 1; } else if (typeof(T) == typeof(byte)) { foreach (var vv in valIndex) { re.Add(datafile.ReadByte(offset + valueaddr + vv)); } datasize = 1; } else if (typeof(T) == typeof(short)) { foreach (var vv in valIndex) { re.Add(datafile.ReadShort(offset + valueaddr + vv * 2)); } datasize = 2; } else if (typeof(T) == typeof(ushort)) { foreach (var vv in valIndex) { re.Add((ushort)datafile.ReadShort(offset + valueaddr + vv * 2)); } datasize = 2; } else if (typeof(T) == typeof(int)) { foreach (var vv in valIndex) { re.Add(datafile.ReadInt(offset + valueaddr + vv * 4)); } datasize = 4; } else if (typeof(T) == typeof(uint)) { foreach (var vv in valIndex) { re.Add((uint)datafile.ReadInt(offset + valueaddr + vv * 4)); } datasize = 4; } else if (typeof(T) == typeof(long)) { foreach (var vv in valIndex) { re.Add((long)datafile.ReadLong(offset + valueaddr + vv * 8)); } datasize = 8; } else if (typeof(T) == typeof(ulong)) { foreach (var vv in valIndex) { re.Add((ulong)datafile.ReadLong(offset + valueaddr + vv * 8)); } datasize = 8; } else if (typeof(T) == typeof(double)) { foreach (var vv in valIndex) { re.Add(datafile.ReadDouble(offset + valueaddr + vv * 8)); } datasize = 8; } else if (typeof(T) == typeof(float)) { foreach (var vv in valIndex) { re.Add(datafile.ReadFloat(offset + valueaddr + vv * 4)); } datasize = 4; } else if (typeof(T) == typeof(string)) { foreach (var vv in valIndex) { var str = Encoding.Unicode.GetString(datafile.ReadBytes(offset + valueaddr + vv * Const.StringSize, Const.StringSize)); re.Add(str); } datasize = Const.StringSize; } else if (typeof(T) == typeof(DateTime)) { foreach (var vv in valIndex) { re.Add(datafile.ReadDateTime(offset + valueaddr + vv * 8)); } datasize = 8; } else if (typeof(T) == typeof(IntPointData)) { foreach (var vv in valIndex) { var x = datafile.ReadInt(offset + valueaddr + vv * 8); var y = datafile.ReadInt(offset + valueaddr + vv * 8 + 4); re.Add(new IntPointData() { X = x, Y = y }); } datasize = 8; } else if (typeof(T) == typeof(UIntPointData)) { foreach (var vv in valIndex) { var x = (uint)datafile.ReadInt(offset + valueaddr + vv * 8); var y = (uint)datafile.ReadInt(offset + valueaddr + vv * 8 + 4); re.Add(new UIntPointData() { X = x, Y = y }); } datasize = 8; } else if (typeof(T) == typeof(LongPointData)) { foreach (var vv in valIndex) { var x = (long)datafile.ReadLong(offset + valueaddr + vv * 16); var y = (long)datafile.ReadLong(offset + valueaddr + vv * 16 + 8); re.Add(new LongPointData() { X = x, Y = y }); } datasize = 16; } else if (typeof(T) == typeof(ULongPointData)) { foreach (var vv in valIndex) { var x = (ulong)datafile.ReadLong(offset + valueaddr + vv * 16); var y = (ulong)datafile.ReadLong(offset + valueaddr + vv * 16 + 8); re.Add(new ULongPointData() { X = x, Y = y }); } datasize = 16; } else if (typeof(T) == typeof(IntPoint3Data)) { foreach (var vv in valIndex) { var x = datafile.ReadInt(offset + valueaddr + vv * 12); var y = datafile.ReadInt(offset + valueaddr + vv * 12 + 4); var z = datafile.ReadInt(offset + valueaddr + vv * 12 + 8); re.Add(new IntPoint3Data() { X = x, Y = y, Z = z }); } datasize = 12; } else if (typeof(T) == typeof(UIntPoint3Data)) { foreach (var vv in valIndex) { var x = (uint)datafile.ReadInt(offset + valueaddr + vv * 12); var y = (uint)datafile.ReadInt(offset + valueaddr + vv * 12 + 4); var z = (uint)datafile.ReadInt(offset + valueaddr + vv * 12 + 8); re.Add(new UIntPoint3Data() { X = x, Y = y, Z = z }); } datasize = 12; } else if (typeof(T) == typeof(LongPoint3Data)) { foreach (var vv in valIndex) { var x = (long)datafile.ReadLong(offset + valueaddr + vv * 24); var y = (long)datafile.ReadLong(offset + valueaddr + vv * 24 + 8); var z = (long)datafile.ReadLong(offset + valueaddr + vv * 24 + 168); re.Add(new LongPoint3Data() { X = x, Y = y, Z = z }); } datasize = 24; } else if (typeof(T) == typeof(ULongPoint3Data)) { foreach (var vv in valIndex) { var x = (ulong)datafile.ReadLong(offset + valueaddr + vv * 24); var y = (ulong)datafile.ReadLong(offset + valueaddr + vv * 24 + 8); var z = (ulong)datafile.ReadLong(offset + valueaddr + vv * 24 + 168); re.Add(new ULongPoint3Data() { X = x, Y = y, Z = z }); } datasize = 24; } datasize = 0; return(re); }