You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
331 lines
13 KiB
331 lines
13 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Data; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Linq.Expressions; |
|
using System.Text; |
|
using System.Reflection; |
|
|
|
namespace EGFramework |
|
{ |
|
/// <summary> |
|
/// CSV Save tools, support read and write CSV file.The dataKey param is not use.please use "" or any string. |
|
/// </summary> |
|
public class EGCsvSave : IEGSaveData, IEGSave, IEGSaveReadOnly |
|
{ |
|
public bool IsReadOnly { get; set; } |
|
public Encoding StringEncoding { set; get; } = Encoding.UTF8; |
|
private string DefaultPath { set; get; } |
|
private List<string[]> CsvDataBlock { get; set; } |
|
private Dictionary<string,int> CsvDataHeader = new Dictionary<string,int>(); |
|
public IOCContainer TypeDataContainer = new IOCContainer(); |
|
private string ReadText { set; get; } |
|
|
|
|
|
public void InitSave(string path) |
|
{ |
|
ReadDataBlock(path); |
|
} |
|
|
|
public void InitReadOnly(string data) |
|
{ |
|
ReadText = data; |
|
if(ReadText != null || ReadText != ""){ |
|
CsvDataBlock = GetCSVDataBlockFromText(ReadText,out CsvDataHeader); |
|
} |
|
} |
|
|
|
public void InitReadOnly(byte[] data) |
|
{ |
|
ReadText = StringEncoding.GetString(data); |
|
if(ReadText != null || ReadText != ""){ |
|
CsvDataBlock = GetCSVDataBlockFromText(ReadText,out CsvDataHeader); |
|
} |
|
} |
|
|
|
public void ReadDataBlock(string path){ |
|
DefaultPath = path; |
|
try |
|
{ |
|
FileStream fileStream = new FileStream(path,FileMode.Open); |
|
byte[] buffer = new byte[fileStream.Length]; |
|
fileStream.Read(buffer, 0, (int)fileStream.Length); |
|
fileStream.Close(); |
|
fileStream.Dispose(); |
|
ReadText = StringEncoding.GetString(buffer); |
|
} |
|
catch (System.Exception e) |
|
{ |
|
EG.Print("e:" + e); |
|
throw; |
|
} |
|
if(ReadText != null || ReadText != ""){ |
|
CsvDataBlock = GetCSVDataBlockFromText(ReadText,out CsvDataHeader); |
|
} |
|
} |
|
|
|
public void WriteDataBlock(string path){ |
|
try |
|
{ |
|
FileStream fileStream = File.Create(path); |
|
string writeText = ""; |
|
string headerText = ""; |
|
foreach(string headStr in CsvDataHeader.Keys){ |
|
headerText+=headStr + ","; |
|
} |
|
headerText = headerText.Remove(headerText.Length-1,1); |
|
writeText = headerText + "\n"; |
|
foreach(string[] lineData in CsvDataBlock){ |
|
string lineText = ""; |
|
foreach(string singleData in lineData){ |
|
lineText += singleData + ","; |
|
} |
|
lineText = lineText.Remove(lineText.Length-1,1); |
|
writeText += lineText + "\n"; |
|
} |
|
writeText = writeText.Remove(writeText.Length-1,1); |
|
byte[] data = StringEncoding.GetBytes(writeText); |
|
fileStream.Write(data,0,data.Length); |
|
fileStream.Close(); |
|
fileStream.Dispose(); |
|
} |
|
catch (System.Exception e) |
|
{ |
|
EG.Print("e:" + e); |
|
throw; |
|
} |
|
} |
|
|
|
public List<string[]> GetCSVDataBlockFromText(string text,out Dictionary<string,int> header){ |
|
List<string[]> csvBlock = new List<string[]>(); |
|
string[] lineData = text.Split('\n'); |
|
string[] headerStr = lineData[0].Split(','); |
|
header = new Dictionary<string,int>(); |
|
for (int i = 0; i < headerStr.Length; i++) |
|
{ |
|
header.Add(headerStr[i],i); |
|
} |
|
for (int lineID = 0; lineID < lineData.Length; lineID++) |
|
{ |
|
if (lineID!=0){ |
|
csvBlock.Add(lineData[lineID].Split(',')); |
|
} |
|
} |
|
return csvBlock; |
|
} |
|
|
|
public string[] ReadLine(int id){ |
|
if(CsvDataBlock.Count()>0){ |
|
return CsvDataBlock[id]; |
|
}else{ |
|
return null; |
|
} |
|
} |
|
|
|
public void WriteLine(string[] lineData){ |
|
CsvDataBlock.Add(lineData); |
|
this.WriteDataBlock(DefaultPath); |
|
} |
|
|
|
public void SetData<TData>(string dataKey, TData data, object id) |
|
{ |
|
if(IsReadOnly){ |
|
throw new Exception("This file is readonly! can't set any data to file."); |
|
} |
|
bool IsAdd = false; |
|
int dataID = 0; |
|
if(id.GetType()==typeof(int)){ |
|
dataID = (int)id; |
|
}else if(int.TryParse(id.ToString() ,out dataID)){ |
|
throw new Exception("Id cannot be convert to int!"); |
|
} |
|
if(dataID>=CsvDataBlock.Count() || dataID < 0){ |
|
IsAdd = true; |
|
} |
|
string[] csvSet = new string[CsvDataHeader.Keys.Count()]; |
|
foreach(PropertyInfo property in data.GetType().GetProperties()){ |
|
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>(); |
|
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){ |
|
csvSet[CsvDataHeader[csvParam._name]] = property.GetValue(data).ToString(); |
|
} |
|
} |
|
if(IsAdd){ |
|
CsvDataBlock.Add(csvSet); |
|
}else{ |
|
CsvDataBlock[dataID] = csvSet; |
|
} |
|
this.WriteDataBlock(DefaultPath); |
|
} |
|
|
|
public TData GetData<TData>(string dataKey, object id) where TData : new() |
|
{ |
|
TData data = new TData(); |
|
int dataID = 0; |
|
if(id.GetType()==typeof(int)){ |
|
dataID = (int)id; |
|
}else if(int.TryParse(id.ToString() ,out dataID)){ |
|
throw new Exception("Id cannot be convert to int!"); |
|
} |
|
if(dataID>=CsvDataBlock.Count()){ |
|
throw new IndexOutOfRangeException("Parameter index is out of range."); |
|
} |
|
foreach(PropertyInfo property in data.GetType().GetProperties()){ |
|
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>(); |
|
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){ |
|
string valueStr = CsvDataBlock[dataID][CsvDataHeader[csvParam._name]]; |
|
if(property.PropertyType==typeof(string)){ |
|
property.SetValue(data,valueStr); |
|
}else{ |
|
property.SetValue(data,Convert.ChangeType(valueStr,property.PropertyType)); |
|
} |
|
} |
|
} |
|
return data; |
|
} |
|
public IEnumerable<TData> GetAll<TData>(string dataKey) where TData : new() |
|
{ |
|
// throw new NotImplementedException(); |
|
List<TData> DataList = new List<TData>(); |
|
PropertyInfo[] properties = typeof(TData).GetProperties(); |
|
for (int dataID = 0; dataID < CsvDataBlock.Count(); dataID++){ |
|
TData data = new TData(); |
|
foreach(PropertyInfo property in properties){ |
|
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>(); |
|
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){ |
|
string valueStr = CsvDataBlock[dataID][CsvDataHeader[csvParam._name]]; |
|
if(property.PropertyType==typeof(string)){ |
|
property.SetValue(data,valueStr); |
|
}else{ |
|
property.SetValue(data,Convert.ChangeType(valueStr,property.PropertyType)); |
|
} |
|
} |
|
} |
|
DataList.Add(data); |
|
} |
|
TypeDataContainer.Register(DataList); |
|
return DataList; |
|
} |
|
|
|
public IEnumerable<TData> FindData<TData>(string dataKey, Expression<Func<TData, bool>> expression) where TData : new() |
|
{ |
|
List<TData> sourceList; |
|
if(TypeDataContainer.self.ContainsKey(typeof(List<TData>))){ |
|
sourceList = TypeDataContainer.Get<List<TData>>(); |
|
}else{ |
|
sourceList = (List<TData>)GetAll<TData>(dataKey); |
|
} |
|
return sourceList.Where(expression.Compile()); |
|
} |
|
|
|
public void AddData<TData>(string dataKey, TData data) |
|
{ |
|
if(IsReadOnly){ |
|
throw new Exception("This file is readonly! can't set any data to file."); |
|
} |
|
string[] csvSet = new string[CsvDataHeader.Keys.Count()]; |
|
foreach(PropertyInfo property in data.GetType().GetProperties()){ |
|
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>(); |
|
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){ |
|
csvSet[CsvDataHeader[csvParam._name]] = property.GetValue(data).ToString(); |
|
} |
|
} |
|
CsvDataBlock.Add(csvSet); |
|
this.WriteDataBlock(DefaultPath); |
|
} |
|
|
|
public void AddData<TData>(string dataKey, IEnumerable<TData> dataSet) |
|
{ |
|
if(IsReadOnly){ |
|
throw new Exception("This file is readonly! can't set any data to file."); |
|
} |
|
foreach(TData data in dataSet){ |
|
string[] csvSet = new string[CsvDataHeader.Keys.Count()]; |
|
foreach(PropertyInfo property in data.GetType().GetProperties()){ |
|
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>(); |
|
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){ |
|
csvSet[CsvDataHeader[csvParam._name]] = property.GetValue(data).ToString(); |
|
} |
|
} |
|
CsvDataBlock.Add(csvSet); |
|
} |
|
this.WriteDataBlock(DefaultPath); |
|
} |
|
|
|
public void RemoveData<TData>(string dataKey, object id) |
|
{ |
|
if(IsReadOnly){ |
|
throw new Exception("This file is readonly! can't set any data to file."); |
|
} |
|
bool IsAdd = false; |
|
int dataID = 0; |
|
if(id.GetType()==typeof(int)){ |
|
dataID = (int)id; |
|
}else if(int.TryParse(id.ToString() ,out dataID)){ |
|
throw new Exception("Id cannot be convert to int!"); |
|
} |
|
if(dataID>=CsvDataBlock.Count() || dataID < 0){ |
|
IsAdd = true; |
|
} |
|
if(IsAdd){ |
|
return; |
|
}else{ |
|
CsvDataBlock.RemoveAt(dataID); |
|
} |
|
this.WriteDataBlock(DefaultPath); |
|
} |
|
|
|
public void UpdateData<TData>(string dataKey, TData data, object id) |
|
{ |
|
if(IsReadOnly){ |
|
throw new Exception("This file is readonly! can't set any data to file."); |
|
} |
|
bool IsAdd = false; |
|
int dataID = 0; |
|
if(id.GetType()==typeof(int)){ |
|
dataID = (int)id; |
|
}else if(int.TryParse(id.ToString() ,out dataID)){ |
|
throw new Exception("Id cannot be convert to int!"); |
|
} |
|
if(dataID>=CsvDataBlock.Count() || dataID < 0){ |
|
IsAdd = true; |
|
} |
|
string[] csvSet = new string[CsvDataHeader.Keys.Count()]; |
|
foreach(PropertyInfo property in data.GetType().GetProperties()){ |
|
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>(); |
|
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){ |
|
csvSet[CsvDataHeader[csvParam._name]] = property.GetValue(data).ToString(); |
|
} |
|
} |
|
if(!IsAdd){ |
|
CsvDataBlock[dataID] = csvSet; |
|
}else{ |
|
throw new Exception("Data not found!"); |
|
} |
|
this.WriteDataBlock(DefaultPath); |
|
} |
|
|
|
public IEnumerable<string> GetKeys() |
|
{ |
|
return CsvDataHeader.Keys; |
|
} |
|
|
|
public bool ContainsKey(string dataKey) |
|
{ |
|
return CsvDataHeader.ContainsKey(dataKey); |
|
} |
|
|
|
public bool ContainsData(string dataKey, object id) |
|
{ |
|
return CsvDataBlock.Count() > 0 && id.GetType() == typeof(int) && (int)id < CsvDataBlock.Count(); |
|
} |
|
} |
|
|
|
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] |
|
public class CsvParamAttribute: Attribute{ |
|
public string _name { set; get; } |
|
public CsvParamAttribute(string name){ |
|
this._name = name; |
|
} |
|
} |
|
} |