今天看啥
    热点:

      天发国际娱乐官网:  席勒,德国18世纪著名诗人、作家、哲学家。

      C#之文件缓存,


      写在开头



        今天就放假了,照理说应该写今年的总结了,但是回头一看,很久没有写过技术类的文字了,还是先不吐槽了。


      关于文件缓存



        写了很多的代码,常常在写EXE(定时任务)或者写小站点(数据的使用和客户端调用之间)都需要用到缓存,数据在内存和文本都保留一个整体。

      当然也可以写到数据库,不过个人觉得不方便查看和管理。(数据量不大)


      第一个版本



        一般来说,就是一个缓存类,然后存放缓存文件路径,真实数据集合,读写集合,读写文件。

        先提供一个公用类

      1 public class TestInfo
      2 {
      3     public string Name { get; set; }
      4 
      5     public int Age { get; set; }
      6 
      7     public string Value { get; set; }
      8 }
      测试公有类

        然后是第一个对文件读写操作的缓存了

       1 public class Cache_Test_1
       2     {
       3         private static List<TestInfo> dataList = new List<TestInfo>();
       4 
       5         private static readonly string cachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache", "test.txt");
       6 
       7         private static readonly string SEP_STR = "---";
       8 
       9         static Cache_Test_1()
      10         {
      11             string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache");
      12             if (!Directory.Exists(dir))
      13             {
      14                 Directory.CreateDirectory(dir);
      15             }
      16 
      17             if (File.Exists(cachePath))
      18             {
      19                 string[] lines = File.ReadAllLines(cachePath, Encoding.UTF8);
      20                 foreach (var line in lines)
      21                 {
      22                     string[] lineArray = line.Split(new string[] { SEP_STR }, StringSplitOptions.None);
      23                     if (lineArray.Length == 3)
      24                     {
      25                         dataList.Add(new TestInfo()
      26                         {
      27                             Name = lineArray[0],
      28                             Age = int.Parse(lineArray[1]),
      29                             Value = lineArray[2]
      30                         });
      31                     }
      32                 }
      33             }
      34         }
      35 
      36         public static void AddInfo(TestInfo info)
      37         {
      38             lock (dataList)
      39             {
      40                 var item = dataList.Find(p => p.Name == info.Name);
      41                 if (item == null)
      42                 {
      43                     dataList.Add(info);
      44                 }
      45                 else
      46                 {
      47                     item.Age = info.Age;
      48                     item.Value = info.Value;
      49                 }
      50 
      51                 WriteFile();
      52             }
      53         }
      54 
      55         public static TestInfo GetInfo(string name)
      56         {
      57             lock (dataList)
      58             {
      59                 return dataList.Find(p => p.Name == name);
      60             }
      61         }
      62 
      63         public static List<TestInfo> GetAll()
      64         {
      65             lock (dataList)
      66             {
      67                 return dataList;
      68             }
      69         }
      70 
      71         private static void WriteFile()
      72         {
      73             StringBuilder content = new StringBuilder();
      74             foreach (var item in dataList)
      75             {
      76                 content.AppendLine(item.Name + SEP_STR + item.Age + SEP_STR + item.Value);
      77             }
      78 
      79             File.WriteAllText(cachePath, content.ToString(), Encoding.UTF8);
      80         }
      81     }
      版本1,文件缓存,固定数据格式和类型

        但是,这样的操作如果多了起来,问题就出来了。每次写一种缓存就要写一个缓存操作的类了,写着写着,这样的体力活就有点累了,于是

      穷则思变,就想,写一个通用一点的吧。于是又了第二个版本

       

      第二个版本


       

        这个版本的目的就是解决重复劳动,见代码

        1 public class Cache_Test_2<T> where T : new()
        2     {
        3         /// <summary>
        4         /// 缓存分隔符
        5         /// </summary>
        6         private static readonly string SEP_STR = "---";
        7 
        8         /// <summary>
        9         /// 缓存临时对象集合
       10         /// </summary>
       11         private static List<T> dataList = new List<T>();
       12 
       13         /// <summary>
       14         /// 缓存文本路径
       15         /// </summary>
       16         private static string cachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache", typeof(T).Name.ToString() + ".txt");
       17 
       18         static Cache_Test_2()
       19         {
       20             string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache");
       21             if (!Directory.Exists(dir))
       22             {
       23                 Directory.CreateDirectory(dir);
       24             }
       25 
       26             if (File.Exists(cachePath))
       27             {
       28                 Type t = typeof(T);
       29                 string[] lines = File.ReadAllLines(cachePath, Encoding.UTF8);
       30                 foreach (var line in lines)
       31                 {
       32                     string[] lineArray = line.Split(new string[] { SEP_STR }, StringSplitOptions.None);
       33                     if (line.Contains(SEP_STR))
       34                     {
       35                         List<PropertyIndexInfo> list = new List<PropertyIndexInfo>();
       36                         T model = new T();
       37                         PropertyInfo[] ps = t.GetProperties();
       38                         for (int i = 0; i < lineArray.Length; i++)
       39                         {
       40                             var p = ps[i];
       41                             if (p.PropertyType == typeof(int))
       42                             {
       43                                 p.SetValue(model, Convert.ToInt32(lineArray[i]), null);
       44                             }
       45                             else if (p.PropertyType == typeof(string))
       46                             {
       47                                 p.SetValue(model, lineArray[i], null);
       48                             }
       49                         }
       50 
       51                         dataList.Add(model);
       52                     }
       53                 }
       54             }
       55         }
       56 
       57         /// <summary>
       58         /// 新增一个缓存
       59         /// </summary>
       60         /// <param name="t"></param>
       61         public static void Add(T t)
       62         {
       63             lock (dataList)
       64             {
       65                 dataList.Add(t);
       66 
       67                 WriteFile();
       68             }
       69         }
       70 
       71         /// <summary>
       72         /// 读取缓存集合
       73         /// </summary>
       74         /// <returns></returns>
       75         public static List<T> GetAll()
       76         {
       77             lock (dataList)
       78             {
       79                 return dataList;
       80             }
       81         }
       82 
       83         /// <summary>
       84         /// 写入缓存文件(全量)
       85         /// </summary>
       86         private static void WriteFile()
       87         {
       88             StringBuilder content = new StringBuilder();
       89             foreach (var item in dataList)
       90             {
       91                 List<string> list = new List<string>();
       92                 var ps = typeof(T).GetProperties();
       93                 foreach (var p in ps)
       94                 {
       95                     object p_object = p.GetValue(item, null);
       96                     string value = p_object.ToString();
       97                     list.Add(value);
       98                 }
       99 
      100                 content.AppendLine(string.Join(SEP_STR, list.ToArray()));
      101             }
      102 
      103             File.WriteAllText(cachePath, content.ToString(), Encoding.UTF8);
      104         }
      105     }
      版本2,通用文件缓存(适合一般场景)

        虽然,第二个版本出来了,但是大多数时候,我们创建缓存都是在已有的类上面进行操作,不然每次创建缓存可能就需要一个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秒不到,还是可以。

       

      总结


       

        没啥好总结的,但是不这样写,感觉不规范。写代码的过程中,总是会遇到,写着写着就变成体力活的代码,这个时候,我们就应该认识到问题了,把体力活改变一下,就不再是体力活。

      让代码更简单,让生活个多彩。

        不足之处,望包含,拍砖,丢鸡蛋。

       

       

       

      www.1click-soft.comtruehttp://www.1click-soft.com/Asp_Netjc/1304203.htmlTechArticleC#之文件缓存, 写在开头 今天就放假了,照理说应该写今年的总结了,但是回头一看,很久没有写过技术类的文字了,还是先不吐槽了。...

      相关文章

        暂无相关文章
      相关搜索:

      帮客评论

      视觉看点
      百度 360 搜狗