private DBHeader ExtractHeader(BinaryReader dbReader) { DBHeader header = null; string signature = dbReader.ReadString(4); if (string.IsNullOrWhiteSpace(signature)) { return(null); } if (signature[0] != 'W') { signature = signature.Reverse(); } switch (signature) { case "WDBC": header = new WDBC(); break; case "WDB2": case "WCH2": header = new WDB2(); break; case "WDB5": header = new WDB5(); break; case "WCH5": header = new WCH5(FileName); break; case "WCH7": header = new WCH7(FileName); break; case "WCH8": header = new WCH8(FileName); break; case "WMOB": case "WGOB": case "WQST": case "WIDB": case "WNDB": case "WITX": case "WNPC": case "WPTX": case "WRDN": header = new WDB(); break; } header?.ReadHeader(ref dbReader, signature); return(header); }
public DBEntry Read(MemoryStream stream, string dbFile) { FileName = dbFile; stream.Position = 0; using (var dbReader = new BinaryReader(stream, Encoding.UTF8)) { DBHeader header = ExtractHeader(dbReader); long pos = dbReader.BaseStream.Position; //No header - must be invalid if (!(header?.IsValidFile ?? false)) { throw new Exception("Unknown file type."); } if (header.RecordCount == 0 || header.RecordSize == 0) { throw new Exception("File contains no records."); } DBEntry entry = new DBEntry(header, dbFile); if (entry.TableStructure == null) { throw new Exception("Definition missing."); } if (header.IsTypeOf <WDBC>() || header.IsTypeOf <WDB2>()) { long stringTableStart = dbReader.BaseStream.Position += header.RecordCount * header.RecordSize; Dictionary <int, string> StringTable = new StringTable().Read(dbReader, stringTableStart); //Get stringtable dbReader.Scrub(pos); ReadIntoTable(ref entry, dbReader, StringTable); //Read data stream.Dispose(); return(entry); } else if (header.IsTypeOf <WDB5>() || header.IsTypeOf <WCH5>()) { WDB5 wdb5 = (header as WDB5); WCH5 wch5 = (header as WCH5); WCH7 wch7 = (header as WCH7); int CopyTableSize = wdb5?.CopyTableSize ?? 0; //Only WDB5 has a copy table //StringTable - only if applicable long copyTablePos = dbReader.BaseStream.Length - CopyTableSize; long indexTablePos = copyTablePos - (header.HasIndexTable ? header.RecordCount * 4 : 0); long wch7TablePos = indexTablePos - (wch7?.UnknownWCH7 * 4 ?? 0); long stringTableStart = wch7TablePos - header.StringBlockSize; Dictionary <int, string> StringTable = new Dictionary <int, string>(); if (!header.HasOffsetTable) //Stringtable is only present if there isn't an offset map { dbReader.Scrub(stringTableStart); StringTable = new StringTable().Read(dbReader, stringTableStart, stringTableStart + header.StringBlockSize); dbReader.Scrub(pos); } //Read the data using (MemoryStream ms = new MemoryStream(header.ReadData(dbReader, pos))) using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8)) { ReadIntoTable(ref entry, dataReader, StringTable); } //Cleanup if (header.IsTypeOf <WDB5>()) { wdb5.OffsetLengths = null; } else if (header.IsTypeOf <WCH5>()) { wch5.OffsetLengths = null; } else if (header.IsTypeOf <WCH7>()) { wch7.OffsetLengths = null; } stream.Dispose(); return(entry); } else if (header.IsTypeOf <WDB>()) { WDB wdb = (WDB)header; wdb.ReadExtendedHeader(dbReader, entry.Build); using (MemoryStream ms = new MemoryStream(wdb.ReadData(dbReader))) using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8)) { ReadIntoTable(ref entry, dataReader, new Dictionary <int, string>()); } stream.Dispose(); return(entry); } else { stream.Dispose(); throw new Exception($"Invalid filetype."); } } }
public DBEntry Read(MemoryStream stream, string dbFile) { FileName = dbFile; stream.Position = 0; using (var dbReader = new BinaryReader(stream, Encoding.UTF8)) { DBHeader header = ExtractHeader(dbReader); long pos = dbReader.BaseStream.Position; //No header - must be invalid if (header == null) { throw new Exception("Unknown file type."); } if (header.CheckRecordSize && header.RecordSize == 0) { throw new Exception("File contains no records."); } if (header.CheckRecordCount && header.RecordCount == 0) { throw new Exception("File contains no records."); } DBEntry entry = new DBEntry(header, dbFile); if (header.CheckTableStructure && entry.TableStructure == null) { throw new Exception("Definition missing."); } if (header is WDC1 wdc1) { Dictionary <int, string> StringTable = wdc1.ReadStringTable(dbReader); wdc1.LoadDefinitionSizes(entry); //Read the data using (MemoryStream ms = new MemoryStream(header.ReadData(dbReader, pos))) using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8)) { wdc1.AddRelationshipColumn(entry); wdc1.SetColumnMinMaxValues(entry); ReadIntoTable(ref entry, dataReader, StringTable); } stream.Dispose(); return(entry); } else if (header.IsTypeOf <WDBC>() || header.IsTypeOf <WDB2>()) { long stringTableStart = dbReader.BaseStream.Position += header.RecordCount * header.RecordSize; Dictionary <int, string> StringTable = new StringTable().Read(dbReader, stringTableStart); //Get stringtable dbReader.Scrub(pos); ReadIntoTable(ref entry, dbReader, StringTable); //Read data stream.Dispose(); return(entry); } else if (header.IsTypeOf <WDB5>() || header.IsTypeOf <WCH5>() || header.IsTypeOf <WDB6>()) { int CopyTableSize = header.CopyTableSize; //Only WDB5 has a copy table uint CommonDataTableSize = header.CommonDataTableSize; //Only WDB6 has a CommonDataTable //StringTable - only if applicable long copyTablePos = dbReader.BaseStream.Length - CommonDataTableSize - CopyTableSize; long indexTablePos = copyTablePos - (header.HasIndexTable ? header.RecordCount * 4 : 0); long wch7TablePos = indexTablePos - (header.UnknownWCH7 * 4); long stringTableStart = wch7TablePos - header.StringBlockSize; Dictionary <int, string> StringTable = new Dictionary <int, string>(); if (!header.HasOffsetTable) //Stringtable is only present if there isn't an offset map { dbReader.Scrub(stringTableStart); StringTable = new StringTable().Read(dbReader, stringTableStart, stringTableStart + header.StringBlockSize); dbReader.Scrub(pos); } //Read the data using (MemoryStream ms = new MemoryStream(header.ReadData(dbReader, pos))) using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8)) { entry.UpdateColumnTypes(); ReadIntoTable(ref entry, dataReader, StringTable); } //Cleanup header.OffsetLengths = null; stream.Dispose(); return(entry); } else if (header.IsTypeOf <WDB>()) { WDB wdb = (WDB)header; using (MemoryStream ms = new MemoryStream(wdb.ReadData(dbReader))) using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8)) { ReadIntoTable(ref entry, dataReader, new Dictionary <int, string>()); } stream.Dispose(); return(entry); } else if (header.IsTypeOf <HTFX>()) { //Load data when needed later stream.Dispose(); return(entry); } else { stream.Dispose(); throw new Exception($"Invalid filetype."); } } }