Skip to content

Instantly share code, notes, and snippets.

@DreamVB
Created October 8, 2021 20:51
Show Gist options
  • Save DreamVB/7d38d898948a3ca5c3a01ef1016ec388 to your computer and use it in GitHub Desktop.
Save DreamVB/7d38d898948a3ca5c3a01ef1016ec388 to your computer and use it in GitHub Desktop.
A small Text formated Single Table Database
TextDB db = new TextDB();
private void NewDatabase()
{
List<string> values = new List<string>();
TextDB.FieldDef fd;
List<TextDB.FieldDef> elms = new List<TextDB.FieldDef>();
fd.Name = "Name";
fd.Length = 10;
elms.Add(fd);
fd.Name = "Age";
fd.Length = 10;
elms.Add(fd);
fd.Name = "Sex";
fd.Length = 1;
elms.Add(fd);
fd.Name = "Working";
fd.Length = 10;
elms.Add(fd);
//Add table
db.NewTable(elms);
//Record 1
values.Add("John");
values.Add("20");
values.Add("M");
values.Add("Yes");
db.AddRecord(values);
values = new List<string>();
//Record 2
values.Add("paula");
values.Add("29");
values.Add("F");
values.Add("No");
db.AddRecord(values);
//Save db
db.SaveDb(@"c:\out\test.txt");
//Clear up
elms = new List<TextDB.FieldDef>();
}
private void ShowNamesInDb()
{
//Load db
db.LoadDb(@"c:\out\test.txt");
//Display person Name
for (int r = 0; r < db.RecordCount; r++)
{
MessageBox.Show(db.GetFeildValue(r, "Name"));
}
}
// DreamVB.TextDB Beta 1
// This is a small single table database that allows you to add fields and set there widths
// This is a project I been working on while trying to learn about databases
// Next version I hope to allow the working with more than one table here are some of the things you can do
// Features
// All the database data resides in memory so it faster
// Add records
// Edit and read record values by using a index or a field name
// Delete records
// Remove all records
// Delete fields by using a index or a field name
// Append new fields all all records data aligns with new appends
// Sort the database by a field only works in ascending order for now
// Locate a record by searching by a field once found the record index is returned.
// Can read and write felid value of Integer, Double, String
// Update allows you to update the current file you opened with OpenDb
// SaveDb allows you to save to a different filename
// Any comments and suggestions are welcome please email me at [email protected]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace DreamVB.TextDB
{
public class TextDB
{
public struct FieldDef
{
public string Name;
public int Length;
}
private List<FieldDef> Fields;
private List<List<string>> _Records;
private string dbFilename { get; set; }
private const string IndexRangeError = "Index Out Of Range";
private int FieldIndex(string fldName)
{
int idx = -1;
for (int x = 0; x < FieldCount; x++)
{
if (Fields[x].Name.Equals(fldName, StringComparison.OrdinalIgnoreCase))
{
idx = x;
break;
}
}
return idx;
}
private string _FixValueSize(string data, int RealLength, int ExpectedLength)
{
//Check of string length of greater then the expected length
if (RealLength > ExpectedLength)
{
//Just extract the string to the expected length
return data.Substring(0, ExpectedLength);
}
else
{
//Return data
return data;
}
}
private string StringPadRight(string S, int padsize)
{
//Get the amount we need to pad
int max = (padsize - S.Length);
//Return the S with padded to right with spaces
return S + new String(' ', max);
}
private List<string> Get_FieldValues(string sLine)
{
List<string> val = new List<string>();
int pos = 0;
string sVal = string.Empty;
for (int x = 0; x < FieldCount; x++)
{
//Get value
sVal = sLine.Substring(pos, Fields[x].Length);
//Add to value list and trim the padding spaces
val.Add(sVal.TrimEnd());
//Get next value position
pos = (pos + Fields[x].Length);
sVal = string.Empty;
}
return val;
}
public TextDB()
{
Fields = new List<FieldDef>();
_Records = new List<List<string>>();
}
public int RecordCount
{
get
{
return _Records.Count();
}
}
public int FieldCount
{
get
{
return Fields.Count();
}
}
public void NewTable(List<FieldDef>FieldStruct)
{
bool found = false;
Fields = new List<FieldDef>();
_Records = new List<List<string>>();
foreach (FieldDef fi in FieldStruct)
{
found = FieldIndex(fi.Name) != -1;
//Check if field is in the Fields list
if (found)
{
//Found exit with error
throw new Exception("Field Already Exists:\n'" + fi.Name + "'");
}
//Add field info
Fields.Add(fi);
}
}
public void AppendField(FieldDef FieldInfo, string vDefaultValue = "")
{
List<string> vals;
//Check if the field name is found in the Fields list
bool found = FieldIndex(FieldInfo.Name) != -1;
if (found)
{
throw new Exception("Field Already Exists:\n'" + FieldInfo.Name + "'");
}
for (int x = 0; x < RecordCount; x++)
{
vals = _Records[x];
//Check length
if (vDefaultValue.Length > FieldInfo.Length)
{
throw new Exception("Value Exceeds Field Length.");
}
vals.Add(vDefaultValue);
_Records[x] = vals;
}
//Add the new field.
Fields.Add(FieldInfo);
}
public void AddRecord(List<string> values)
{
if (values.Count() != FieldCount)
{
throw new Exception(IndexRangeError);
}
//Add new record.
_Records.Add(values);
}
public string GetFeildValue(int record, int index)
{
if (record < 0 || record > RecordCount)
{
throw new Exception(IndexRangeError);
}
else if (index < 0 || index > FieldCount)
{
throw new Exception(IndexRangeError);
}
else
{
return _Records[record][index];
}
}
public string GetFeildValue(int record, string fldName)
{
//Get field index
int idx = FieldIndex(fldName);
//Return field value
return GetFeildValue(record, idx);
}
public int GetFieldInteger(int record, int index)
{
string tmp = GetFeildValue(record, index);
try
{
return int.Parse(tmp);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public int GetFieldInteger(int record, string fldName)
{
int idx = FieldIndex(fldName);
return GetFieldInteger(record, idx);
}
public void SetFieldIntegter(int record, int index, int value)
{
SetFieldValue(record, index, value.ToString());
}
public void SetFieldIntegter(int record, string fldName, int value)
{
int idx = FieldIndex(fldName);
SetFieldValue(record, idx, value.ToString());
}
public double GetFieldDouble(int record, int index)
{
string tmp = GetFeildValue(record, index);
try
{
return double.Parse(tmp);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public double GetFieldDouble(int record, string fldName)
{
int idx = FieldIndex(fldName);
return GetFieldDouble(record, idx);
}
public void SetFieldDouble(int record, int index, double value)
{
SetFieldValue(record, index, value.ToString());
}
public void SetFieldDouble(int record, string fldName, double value)
{
int idx = FieldIndex(fldName);
SetFieldValue(record, idx, value.ToString());
}
public void SetFieldValue(int record, int index, string value)
{
if (record < 0 || record > RecordCount)
{
throw new Exception(IndexRangeError);
}
else if (index < 0 || index > FieldCount)
{
throw new Exception(IndexRangeError);
}
else if (value.Length > Fields[index].Length)
{
throw new Exception("Value Exceeds Field Length");
}
{
_Records[record][index] = value;
}
}
public void SetFieldValue(int record, string fldName, string value)
{
int idx = FieldIndex(fldName);
SetFieldValue(record, idx, value);
}
public string GetFieldName(int index)
{
if (index < 0 || index > FieldCount)
{
throw new Exception(IndexRangeError);
}
return Fields[index].Name;
}
public int GetFieldLength(int index)
{
if (index < 0 || index > FieldCount)
{
throw new Exception(IndexRangeError);
}
return Fields[index].Length;
}
public int GetFieldLength(string fldName)
{
int idx = FieldIndex(fldName);
return GetFieldLength(idx);
}
public int FindRecord(int index, string Term)
{
int r_idx = (-1);
if (index < 0 || index > FieldCount)
{
throw new Exception(IndexRangeError);
}
//Loop though the records
for (int x = 0; x < RecordCount; x++)
{
//Check the record field value is the same as Term
if (_Records[x][index].Equals(Term, StringComparison.OrdinalIgnoreCase))
{
r_idx = x;
break;
}
}
return r_idx;
}
public int FindRecord(string fldName, string Term)
{
int idx = FieldIndex(fldName);
return FindRecord(idx, Term);
}
public void SortRecords(int index)
{
if (index < 0 || index > FieldCount)
{
throw new Exception(IndexRangeError);
}
//Loop though all the records
for (int i = 0; i < RecordCount; i++)
{
for (int j = i + 1; j < RecordCount; j++)
{
if (string.Compare(_Records[i][index], _Records[j][index], true) > 0)
{
var k = _Records[i];
_Records[i] = _Records[j];
_Records[j] = k;
}
}
}
}
public void SortRecords(string SortField)
{
int idx = FieldIndex(SortField);
SortRecords(idx);
}
public void DeleteRecord(int index)
{
if (index < 0 || index > RecordCount)
{
throw new Exception(IndexRangeError);
}
try
{
//Delete the record
_Records.RemoveAt(index);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public void DeleteAllRecords()
{
try
{
_Records.Clear();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public void DeleteField(int index)
{
List<string> vals;
//Check for index out of range
if (index < 0 || index > FieldCount)
{
throw new Exception(IndexRangeError);
}
//Sort the records
for (int x = 0; x < RecordCount; x++)
{
//Get record.
vals = _Records[x];
//Delete the value at the index level
vals.RemoveAt(index);
//Set the record
_Records[x] = vals;
}
//Delete the field name
Fields.RemoveAt(index);
}
public void DeleteField(string fldName)
{
int idx = FieldIndex(fldName);
//Delete the field.
DeleteField(idx);
}
public void LoadDb(string Filename)
{
string[] Lines;
int ln = 0;
string[] fldLine;
List<string> values;
List<FieldDef> elms = new List<FieldDef>();
FieldDef fi;
bool IsFirstLine = true;
string sLine = string.Empty;
//Load the whole file.
_Records = new List<List<string>>();
Fields = new List<FieldDef>();
//Set db filename
dbFilename = Filename;
if (!File.Exists(dbFilename))
{
throw new FileNotFoundException("File Was Not Found:\n" +
Filename);
}
try
{
Lines = File.ReadAllLines(dbFilename);
while (ln < Lines.Length)
{
sLine = Lines[ln];
if (sLine.Trim().Length == 0)
{
continue;
}
else
{
//Get very first line this is the fields description
if (IsFirstLine)
{
fldLine = sLine.Split('|');
//Get the field name and field length
foreach (string fld in fldLine)
{
string[] fInfo = fld.Split(':');
fi.Name = fInfo[0];
fi.Length = Convert.ToInt32(fInfo[1]);
//Add the field description
elms.Add(fi);
}
//Add the fields.
NewTable(elms);
//Clear array
elms = new List<FieldDef>();
Array.Clear(fldLine, 0, fldLine.Length);
//Set first line to false.
IsFirstLine = false;
}
else
{
//Get values
values = Get_FieldValues(sLine);
//Add records
_Records.Add(values);
}
}
//INC line counter
ln++;
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
//Clear lines
Array.Clear(Lines, 0, Lines.Length);
}
public void UpdateDb()
{
if (dbFilename.Length.Equals(0))
{
return;
}
if (File.Exists(dbFilename))
{
SaveDb(dbFilename);
}
}
public void SaveDb(string Filename)
{
StringBuilder sb = new StringBuilder();
string sLine = string.Empty;
string fldValue = string.Empty;
//Add fields
foreach (FieldDef fi in Fields)
{
sLine += fi.Name + ":" + fi.Length.ToString() + "|";
//Add to string builder
}
//Trim last |
sLine = sLine.TrimEnd('|');
sb.AppendLine(sLine);
//Clear string
sLine = string.Empty;
//Append records.
for (int x = 0; x < RecordCount; x++)
{
for (int y = 0; y < FieldCount; y++)
{
//Get field value
fldValue = _Records[x][y];
fldValue = _FixValueSize(fldValue, fldValue.Length, Fields[y].Length);
fldValue = StringPadRight(fldValue, Fields[y].Length);
//Set the line to be added to the string collection.
sLine += fldValue;
}
//Append to string builder
sb.AppendLine(sLine);
//Clear string
sLine = string.Empty;
}
try
{
//Write string builder to file.
File.WriteAllText(Filename, sb.ToString());
//Clear the string builder object
sb.Clear();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment