using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Collections.ObjectModel; using System.IO; using System.Text.RegularExpressions; namespace FLY.Thick.RemoteHistory { public interface IFlyData { DateTime Time { get; set; } string GetHeader(); string ToString(); bool TryParse(string header_str, string str); } /// <summary> /// 历史数据, 保存格式为 csv /// </summary> /// <typeparam name="T"></typeparam> public interface IHistory<T> : IRemoteHistory where T : IFlyData { /// <summary> /// 设置自定义的部分文件名,不能出现特殊符号 “.” 都不可以 /// </summary> string FileNameCustom{get;set;} /// <summary> /// 数据添加 /// </summary> /// <param name="t"></param> void AddRange(IEnumerable<T> t_array); void Add( T t); /// <summary> /// 根路径 /// </summary> string RootPath{get;set;} } /// <summary> /// 历史数据, 保存格式为 csv /// </summary> public class History<T> : IHistory<T> where T : IFlyData { private List<T> datas = new List<T>(); /// <summary> /// 已经保存了数据的日期, /// </summary> private List<DateTime> dateInRootPath = new List<DateTime>(); public History(string rootpath) { KeeyDay = 180; SaveRows = 200; RootPath = rootpath; FileNameCustom = null; CurrPath = null; CurrRows = 0; InitKeepDay(); } #region IHistory<T> 成员 private string filenamecustom; /// <summary> /// 设置自定义的部分文件名,不能出现特殊符号 “.” 都不可以 /// </summary> public string FileNameCustom { get { return filenamecustom; } set { if (filenamecustom != value) { Flush(); filenamecustom = value; NotifyPropertyChanged("FileNameCustom"); } } } private int currdays = 0; /// <summary> /// 当前保存的数据天数 /// </summary> public int CurrDays { get { return currdays; } protected set { if (currdays != value) { currdays = value; NotifyPropertyChanged("CurrDays"); } } } private int keeyday; /// <summary> /// 数据能保存的天数 /// </summary> public int KeeyDay { get { return keeyday; } set { if (value <= 0) value = 1; if (keeyday != value) { keeyday = value; NotifyPropertyChanged("KeeyDay"); } } } private string rootpath; /// <summary> /// 根路径 /// </summary> public string RootPath { get { return rootpath; } set { if (rootpath != value) { rootpath = value; NotifyPropertyChanged("RootPath"); } } } private int saverows; /// <summary> /// 多少行保存一次 /// </summary> public int SaveRows { get { return saverows; } set { if (saverows != value) { saverows = value; NotifyPropertyChanged("SaveRows"); } } } private int currrows; /// <summary> /// 当前总行数 /// </summary> public int CurrRows { get { return currrows; } set { if (currrows != value) { currrows = value; NotifyPropertyChanged("CurrRows"); } } } private string currpath=null; public string CurrPath { get { return currpath; } set { if (currpath != value) { currpath = value; NotifyPropertyChanged("CurrPath"); } } } #endregion #region IHistory void CreateCurrPath() { if (CurrPath == null) { //创建路径 DateTime dt = datas.First().Time; string dirpath = RootPath + @"\" + dt.ToString(@"yyyy\\MM\\dd"); Directory.CreateDirectory(dirpath); Keep(dt); if (string.IsNullOrEmpty(FileNameCustom)) { CurrPath = dirpath + @"\" + dt.ToString("HH_mm_ss") + ".csv"; } else { CurrPath = dirpath + @"\" + dt.ToString("HH_mm_ss") + "_" + FileNameCustom + ".csv"; } } } public void Flush() { if (datas.Count() == 0) return; if (string.IsNullOrEmpty(CurrPath)) { CreateCurrPath(); } //以附加的方式打开只写文件。 //若文件不存在,则会建立该文件, //如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。 StreamWriter sw = new StreamWriter(CurrPath, true, Encoding.GetEncoding("GB2312")); sw.WriteLine(datas[0].GetHeader()); for (int i = 0; i < datas.Count; i++) sw.WriteLine(datas[i].ToString()); datas.Clear(); sw.Flush(); sw.Close(); CurrRows = 0; CurrPath = null; } public void AddRange(IEnumerable<T> t_array) { datas.AddRange(t_array); UpdateAdd(); } public void Add(T t) { datas.Add(t); UpdateAdd(); } void UpdateAdd() { CurrRows = datas.Count; if ((CurrRows >= 1) && (CurrPath == null)) { CreateCurrPath(); } else if (datas.Count >= SaveRows) { //保存数据 Flush(); } } #endregion public void Apply() { } //获取历史数据 public void GetPaths(DateTime dt_begin, DateTime dt_end, string profilename,GetPathsReponseHandler return_func, object state) { List<string> paths = GetPaths(dt_begin, dt_end, profilename); return_func(paths,state); } List<string> GetPaths(DateTime dt_begin, DateTime dt_end, string profilename) { List<string> paths = new List<string>(); Regex regex_file; if (profilename != null) { string unescape = Regex.Escape(profilename); regex_file = new Regex(@"\d{2}_\d{2}_\d{2}_.*" + unescape + @".*\.csv"); } else regex_file = new Regex(@"\d{2}_\d{2}_\d{2}.*\.csv"); for (int i = 0; i < dateInRootPath.Count(); i++) { if ((dateInRootPath[i].Date >= dt_begin.Date) && (dateInRootPath[i].Date <= dt_end.Date)) { DateTime dt = dateInRootPath[i].Date; string dirpath = RootPath + @"\" + dt.ToString(@"yyyy\\MM\\dd"); DirectoryInfo mydir = new DirectoryInfo(dirpath); FileSystemInfo[] fsil_file = mydir.GetFileSystemInfos(); for (int j = 0; j < fsil_file.Count(); j++) { FileSystemInfo fsi = fsil_file[j]; if((fsi.Attributes != FileAttributes.Directory) && (regex_file.IsMatch(fsi.Name))) { paths.Add(dirpath + @"\" + fsi.Name); } } //var fsil_file = from fsi in mydir.GetFileSystemInfos() // where (fsi.Attributes == FileAttributes.Normal) && (regex_file.IsMatch(fsi.Name)) // select fsi; //foreach (FileSystemInfo fsi in fsil_file) //{ // paths.Add(dirpath + @"\" + fsi.Name); //} } else if (dateInRootPath[i].Date > dt_end.Date) { break; } } return paths; } public void GetRootPath(GetRootPathReponseHandler return_func, object state) { string path = System.Environment.CurrentDirectory; return_func(path, state); } #region 自动删数据 private void InitKeepDay() { dateInRootPath.Clear(); if (!Directory.Exists(RootPath)) { Directory.CreateDirectory(RootPath); return; } DirectoryInfo mydir = new DirectoryInfo(RootPath); //年 Regex regex_year = new Regex(@"\d{4}"); Regex regex_month = new Regex(@"\d{2}"); Regex regex_day = new Regex(@"\d{2}"); var fsil_year = from fsi in mydir.GetFileSystemInfos() where (fsi.Attributes == FileAttributes.Directory) && (regex_year.IsMatch(fsi.Name)) select fsi; foreach (var fsi_year in fsil_year) { var fsil_month = from fsi in ((DirectoryInfo)fsi_year).GetFileSystemInfos() where (fsi.Attributes == FileAttributes.Directory) && (regex_month.IsMatch(fsi.Name)) select fsi; foreach (var fsi_month in fsil_month) { var fsil_day = from fsi in ((DirectoryInfo)fsi_month).GetFileSystemInfos() where (fsi.Attributes == FileAttributes.Directory) && (regex_day.IsMatch(fsi.Name)) select fsi; foreach (var fsi_day in fsil_day) { DateTime dt = new DateTime( int.Parse(fsi_year.Name), int.Parse(fsi_month.Name), int.Parse(fsi_day.Name)); //if (DateTime.TryParse(fsi_year.Name.ToString() + "-" + fsi_month.Name.ToString() + "-" + fsi_day.Name.ToString(), out dt)) { dateInRootPath.Add(dt); } } } } dateInRootPath.Sort(new Comparison<DateTime>( delegate(DateTime t1, DateTime t2) { if (t1 > t2) return 1; else if (t1 == t2) return 0; else return -1; })); CurrDays = dateInRootPath.Count; Keep(); } private void Keep() { while (dateInRootPath.Count > KeeyDay) { string dirpath = RootPath+@"\"+dateInRootPath.First().ToString(@"yyyy\\MM\\dd"); Directory.Delete(dirpath,true); dateInRootPath.RemoveAt(0); } CurrDays = dateInRootPath.Count; } private void Keep(DateTime dt) { if (dateInRootPath.Count() > 0) { DateTime last = dateInRootPath.Last(); if (last.Date == dt.Date) return; } dateInRootPath.Add(dt.Date); Keep(); } #endregion #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged(string propertyname) { if(PropertyChanged!=null) PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname)); } #endregion } }