JsonDB/IO/LocalStore.cs

145 lines
3.7 KiB
C#

using System.Text;
using System.Text.Json;
namespace DevJsonDB.IO;
public class LocalStore<T> : IStore<T>
{
private static Encoding DefaultEncoding = Encoding.UTF8;
private string filePath;
private List<T> items;
private bool autoCommit;
public LocalStore(string filePath, bool autoCommit)
{
this.filePath = filePath;
this.items = new List<T>();
this.autoCommit = autoCommit;
this.InitDatabase();
}
public void Dispose()
{
this.Commit();
}
public void Commit()
{
try
{
using (FileStream fs = new FileStream(this.filePath, FileMode.OpenOrCreate))
using (StreamWriter writer = new StreamWriter(fs, DefaultEncoding))
{
fs.Seek(0, SeekOrigin.Begin);
fs.SetLength(0);
for (int i = 0 ; i < items.Count; i++)
{
T item = items[i];
string json = JsonSerializer.Serialize<T>(item);
writer.Write(json);
if (i != items.Count - 1)
{
writer.Write("\n");
}
}
}
}
catch (Exception ex)
{
throw new JsonDBException(ex.Message, ex);
}
}
public bool Add(T item)
{
if (this.items.Contains(item))
{
return false;
}
this.items.Add(item);
this.AutoCommit(FastMergeType.Add);
return true;
}
public bool Has(T item)
{
return this.items.Contains(item);
}
public bool Remove(T item)
{
bool ret = this.items.Remove(item);
this.AutoCommit(FastMergeType.Remove);
return ret;
}
public IEnumerable<T> GetValues()
{
return this.items.ToList();
}
private void AutoCommit(FastMergeType mergeType)
{
if (!this.autoCommit) return;
try
{
// Fast-Merge
switch (mergeType)
{
case FastMergeType.Add:
{
using (FileStream fs = new FileStream(this.filePath, FileMode.Append))
using (StreamWriter writer = new StreamWriter(fs, DefaultEncoding))
{
T lastItem = this.items.ElementAt(this.items.Count() - 1);
string json = JsonSerializer.Serialize<T>(lastItem);
if (fs.Length > 0)
{
writer.Write("\n");
}
writer.Write(json);
}
break;
}
case FastMergeType.Remove:
{
this.Commit();
break;
}
}
}
catch (Exception ex)
{
throw new JsonDBException(ex.Message, ex);
}
}
private void InitDatabase()
{
try
{
using (FileStream fs = new FileStream(this.filePath, FileMode.OpenOrCreate))
using (StreamReader reader = new StreamReader(fs, DefaultEncoding))
{
string? line = null;
while ((line = reader.ReadLine()) != null)
{
T? value = JsonSerializer.Deserialize<T>(line);
if (value is object)
{
this.items.Add(value);
}
}
}
}
catch (Exception ex)
{
throw new JsonDBException(ex.Message, ex);
}
}
}