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."); } } }