首页 > Python基础教程 >
-
C#教程之C#之文件缓存
写在开头
今天就放假了,照理说应该写今年的总结了,但是回头一看,很久没有写过技术类的文字了,还是先不吐槽了。
关于文件缓存
写了很多的代码,常常在写EXE(定时任务)或者写小站点(数据的使用和客户端调用之间)都需要用到缓存,数据在内存和文本都保留一个整体。
当然也可以写到数据库,不过个人觉得不方便查看和管理。(数据量不大)
第一个版本
一般来说,就是一个缓存类,然后存放缓存文件路径,真实数据集合,读写集合,读写文件。
先提供一个公用类
然后是第一个对文件读写操作的缓存了
但是,这样的操作如果多了起来,问题就出来了。每次写一种缓存就要写一个缓存操作的类了,写着写着,这样的体力活就有点累了,于是
穷则思变,就想,写一个通用一点的吧。于是又了第二个版本
第二个版本
这个版本的目的就是解决重复劳动,见代码
虽然,第二个版本出来了,但是大多数时候,我们创建缓存都是在已有的类上面进行操作,不然每次创建缓存可能就需要一个CacheModel这样一个对象了,
这样还有,并不是所有的字段我们都是需要进入缓存文件,这样的情况该如何操作呢,于是我们再次优化了一下代码,出现了目前来说的第三个版本了。
第三个版本
这里,就会新增几个类了,为了解决第二个版本不能解决的问题,当然具体使用还是要看业务场景,因为,更通用就代表更依赖配置了。(代码类)
这里需要几个基本类,用来保存临时管理的。
1 /// <summary> 2 /// 特性:指定属性的排序和是否出现在缓存中使用 3 /// </summary> 4 public class CacheOrderAttribute : Attribute 5 { 6 public int Index { get; set; } 7 } 8 9 /// <summary> 10 /// 对字符串分割的结果的值进行排序 11 /// </summary> 12 public class CacheIndexInfo 13 { 14 public int Index { get; set; } 15 16 public string Value { get; set; } 17 } 18 19 /// <summary> 20 /// 对字段的属性进行排序 21 /// </summary> 22 public class PropertyIndexInfo 23 { 24 public int Index { get; set; } 25 26 public PropertyInfo PropertyInfo { get; set; } 27 }
有了特性,我们就能对单个类的属性进行特性筛查,排序,最终得到我们需要的和不需要的,最开始改好了,楼主测试了一下,速度上还可以,但是数据了一多,
这种每次全部写入文件的方式就low了,于是改成了Append的方式,大大提升了速度。同时添加了一个类,对具体分割的值进行调整的。代码如下:
1 /// <summary> 2 /// 文件缓存共有类 3 /// </summary> 4 /// <typeparam name="T">类</typeparam> 5 public class File_Common_Cache<T> where T : new() 6 { 7 /// <summary> 8 /// 缓存分隔符 9 /// </summary> 10 private static string SEP_STR = "---"; 11 12 /// <summary> 13 /// 缓存临时对象集合 14 /// </summary> 15 private static List<T> dataList = new List<T>(); 16 17 /// <summary> 18 /// 缓存文本路径 19 /// </summary> 20 private static string cachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache", typeof(T).Name.ToString() + ".txt"); 21 22 static File_Common_Cache() 23 { 24 string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache"); 25 if (!Directory.Exists(dir)) 26 { 27 Directory.CreateDirectory(dir); 28 } 29 30 if (File.Exists(cachePath)) 31 { 32 Type t = typeof(T); 33 string[] lines = File.ReadAllLines(cachePath, Encoding.UTF8); 34 foreach (var line in lines) 35 { 36 string[] lineArray = line.Split(new string[] { SEP_STR }, StringSplitOptions.None); 37 if (line.Contains(SEP_STR)) 38 { 39 List<PropertyIndexInfo> list = new List<PropertyIndexInfo>(); 40 T model = new T(); 41 PropertyInfo[] ps = t.GetProperties(); 42 foreach (var p in ps) 43 { 44 var ads = p.GetCustomAttributesData(); 45 if (ads.Count > 0) 46 { 47 int index = Convert.ToInt32(ads[0].NamedArguments[0].TypedValue.Value); 48 list.Add(new PropertyIndexInfo() { Index = index, PropertyInfo = p }); 49 } 50 } 51 52 list = list.OrderBy(p => p.Index).ToList(); 53 for (int i = 0; i < list.Count; i++) 54 { 55 var pt = list[i].PropertyInfo.PropertyType; 56 if (pt == typeof(int)) 57 { 58 list[i].PropertyInfo.SetValue(model, Convert.ToInt32(lineArray[i]), null); 59 } 60 else if (pt == typeof(string)) 61 { 62 list[i].PropertyInfo.SetValue(model, lineArray[i], null); 63 } 64 else if (pt == typeof(DateTime)) 65 { 66 list[i].PropertyInfo.SetValue(model, Convert.ToDateTime(lineArray[i]), null); 67 } 68 else 69 { 70 try 71 { 72 list[i].PropertyInfo.SetValue(model, (object)lineArray[i], null); 73 } 74 catch 75 { 76 throw new Exception("不支持属性类型(仅支持,int,string,DateTime,object)"); 77 } 78 } 79 } 80 81 dataList.Add(model); 82 } 83 } 84 } 85 } 86 87 /// <summary> 88 /// 初始化配置(修改默认分割和保存文件使用) 89 /// </summary> 90 /// <param name="sep_str">分隔符</param> 91 /// <param name="fileName">缓存文件名</param> 92 public static void InitSet(string sep_str, string fileName) 93 { 94 SEP_STR = sep_str; 95 cachePath = fileName; 96 } 97 98 /// <summary> 99 /// 新增一个缓存 100 /// </summary> 101 /// <param name="t"></param> 102 public static void Add(T t) 103 { 104 lock (dataList) 105 { 106 dataList.Add(t); 107 108 AppendFile(t); 109 } 110 } 111 112 /// <summary> 113 /// 移除一个缓存 114 /// </summary> 115 /// <param name="t"></param> 116 public static void Remove(T t) 117 { 118 119 } 120 121 /// <summary> 122 /// 读取缓存集合 123 /// </summary> 124 /// <returns></returns> 125 public static List<T> GetAll() 126 { 127 lock (dataList) 128 { 129 return dataList; 130 } 131 } 132 133 /// <summary> 134 /// 写入缓存文件(全量) 135 /// </summary> 136 private static void WriteFile() 137 { 138 StringBuilder content = new StringBuilder(); 139 foreach (var item in dataList) 140 { 141 List<CacheIndexInfo> list = new List<CacheIndexInfo>(); 142 var ps = typeof(T).GetProperties(); 143 foreach (var p in ps) 144 { 145 var ads = p.GetCustomAttributesData(); 146 if (ads.Count > 0) 147 { 148 int index = Convert.ToInt32(ads[0].NamedArguments[0].TypedValue.Value); 149 object p_object = p.GetValue(item, null); 150 string value = string.Empty; 151 if (p.PropertyType == typeof(DateTime)) 152 { 153 value = p_object == null ? DateTime.Parse("1900-1-1").ToString("yyyy-MM-dd HH:mm:ss") : 154 Convert.ToDateTime(p_object).ToString("yyyy-MM-dd HH:mm:ss"); 155 } 156 else 157 { 158 value = p_object == null ? "" : p_object.ToString(); 159 } 160 161 list.Add(new CacheIndexInfo() { Index = index, Value = value }); 162 } 163 } 164 165 list = list.OrderBy(a => a.Index).ToList(); 166 content.AppendLine(string.Join(SEP_STR, (from f in list select f.Value).ToArray())); 167 } 168 169 File.WriteAllText(cachePath, content.ToString(), Encoding.UTF8); 170 } 171 172 /// <summary> 173 /// 写入缓存文件(附加) 174 /// </summary> 175 /// <param name="t"></param> 176 private static void AppendFile(T t) 177 { 178 StringBuilder content = new StringBuilder(); 179 List<CacheIndexInfo> list = new List<CacheIndexInfo>(); 180 var ps = typeof(T).GetProperties(); 181 foreach (var p in ps) 182 { 183 var ads = p.GetCustomAttributesData(); 184 if (ads.Count > 0) 185 { 186 int index = Convert.ToInt32(ads[0].NamedArguments[0].TypedValue.Value); 187 object p_object = p.GetValue(t, null); 188 string value = string.Empty; 189 if (p.PropertyType == typeof(DateTime)) 190 { 191 value = p_object == null ? DateTime.Parse("1900-1-1").ToString("yyyy-MM-dd HH:mm:ss") : 192 Convert.ToDateTime(p_object).ToString("yyyy-MM-dd HH:mm:ss"); 193 } 194 else 195 { 196 value = p_object == null ? "" : p_object.ToString(); 197 } 198 199 list.Add(new CacheIndexInfo() { Index = index, Value = value }); 200 } 201 } 202 203 list = list.OrderBy(a => a.Index).ToList(); 204 content.AppendLine(string.Join(SEP_STR, (from f in list select f.Value).ToArray())); 205 File.AppendAllText(cachePath, content.ToString(), Encoding.UTF8); 206 } 207 }
测试代码
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 TInfo info = new TInfo(); 6 info.Name = "test"; 7 info.Age = 10; 8 info.Test = "我是测试字符串"; 9 var list = File_Common_Cache<TInfo>.GetAll(); 10 DateTime startTime = DateTime.Now; 11 for (int i = 0; i < 1000; i++) 12 { 13 File_Common_Cache<TInfo>.Add(info); 14 } 15 16 TimeSpan span = DateTime.Now - startTime; 17 Console.WriteLine(span.TotalMilliseconds); 18 Console.ReadLine(); 19 } 20 } 21 22 public class TInfo 23 { 24 [CacheOrder(Index = 0)] 25 public string Name { get; set; } 26 27 [CacheOrder(Index = 2)] 28 public int Age { get; set; } 29 30 [CacheOrder(Index = 1)] 31 public string Test { get; set; } 32 }
测试结果:1秒不到,还是可以。
总结
没啥好总结的,但是不这样写,感觉不规范。写代码的过程中,总是会遇到,写着写着就变成体力活的代码,这个时候,我们就应该认识到问题了,把体力活改变一下,就不再是体力活。
让代码更简单,让生活个多彩。
不足之处,望包含,拍砖,丢鸡蛋。