前言:自定义写入日志,需要注意多线程下文件读取写入时异常问题处理:下面列举了2种优化方案:
废话不多说,直接上代码:
很简单:将类复制到项目中,最后在配置文件上配置一下:logUrl即可。 默认保存在:项目/temp/log
自定义日志类1:
/// <summary> /// 日志类 /// </summary> /// <remarks>Creator: v-lxh CreateTime: 2016/7/26 11:18:09</remarks> /// <Description></Description> public class Log { /// <summary> /// 写入日志. /// </summary> /// <param name="strList">The STR list.</param> /// <remarks>Creator: v-lxh CreateTime: 2016/7/26 11:18:09</remarks> /// <Description></Description> public static void WriteLog(params object[] strList) { //判断是否开启日志模式 //if (!LogModel) return; if (strList.Count() == 0) return; //日志文件路径 string strDicPath = ""; try { strDicPath = HttpContext.Current.Server.MapPath("~/temp/log/"); if (strDicPath == null || strDicPath == "") { strDicPath = System.Configuration.ConfigurationManager.AppSettings["logUrl"] + "/temp/log/"; } } catch (Exception e) { strDicPath = System.Configuration.ConfigurationManager.AppSettings["logUrl"] + "/temp/log/"; } string strPath = strDicPath + string.Format("{0:yyyy年-MM月-dd日}", DateTime.Now) + "日志记录.txt"; if (!Directory.Exists(strDicPath)) { Directory.CreateDirectory(strDicPath); } if (!File.Exists(strPath)) { using (FileStream fs = File.Create(strPath)) { } } string str = File.ReadAllText(strPath); StringBuilder sb = new StringBuilder(); foreach (var item in strList) { sb.Append(" " + DateTime.Now.ToString() + "-----" + item + ""); } File.WriteAllText(strPath, sb.ToString() + " -----z----- " + str); } }
初稿1--优化1-使用Lock锁定资源:
/// <summary> /// 日志类 /// </summary> /// <remarks>Creator: lixh CreateTime: 2017/3/23 11:18:09</remarks> /// <Description></Description> public class Log { //日期文件夹路径 public static string strDicPath = ""; //静态方法todo:在处理话类型之前自动调用,去检查日志文件夹是否存在 static Log() { //todo:通过当前http请求上下文获取的服务器相对路径下的物理路径--非静态资源--占用资源 //string strDicPath = System.Web.HttpContext.Current.Server.MapPath("~/temp/log/"); //静态类型--获取应用所在的物理路径--节省资源 //strDicPath = System.Web.HttpRuntime.AppDomainAppPath + "\temp\logs\";
//winform等非web程序可使用以下方法:
strDicPath = System.Threading.Thread.GetDomain().BaseDirectory.Replace("\bin\Debug", "") + "\temp\logs\";
//创建文件夹 if (!Directory.Exists(strDicPath)) { Directory.CreateDirectory(strDicPath); } } /// <summary> /// 写入日志. /// </summary> /// <param name="strList">The STR list.</param> /// <remarks> </remarks> /// <Description></Description> public static void WriteLog(params object[] strList) { if (strList.Count() == 0) return; string strPath = ""; //文件路径 try { strPath = strDicPath + string.Format("{0:yyyy年-MM月-dd日}", DateTime.Now) + "日志记录.txt"; } catch (Exception e) { strDicPath = "C:\temp\log\"; strPath = strDicPath + string.Format("{0:yyyy年-MM月-dd日}", DateTime.Now) + "日志记录.txt"; } //todo:自动创建文件(但不能创建文件夹),并设置文件内容追加模式,使用using会自动释放FileSteam资源 using (FileStream stream = new FileStream(strPath, FileMode.Append)) { lock (stream) //锁定资源,一次只允许一个线程写入 { StreamWriter write = new StreamWriter(stream); string content = ""; foreach (var str in strList) { content += " " + DateTime.Now.ToString() + "-----" + str; } content += " -----z----- "; write.WriteLine(content); //关闭并销毁流写入文件 write.Close(); write.Dispose(); } } } /// <summary> /// 写入日志. /// </summary> /// <param name="strList">The STR list.</param> /// <remarks></remarks> /// <Description></Description> public static void WriteLog(Action DefFunc, Func<string> ErrorFunc = null) { try { DefFunc(); } catch (Exception ex) { string strPath = strDicPath + string.Format("{0:yyyy年-MM月-dd日}", DateTime.Now) + "日志记录.txt"; //todo:自动创建文件(但不能创建文件夹),并设置文件内容追加模式,使用using会自动释放FileSteam资源 using (FileStream stream = new FileStream(strPath, FileMode.Append)) { lock (stream) //锁定资源,一次只允许一个线程写入 { StreamWriter write = new StreamWriter(stream); string content = " " + DateTime.Now.ToString() + "-----" + ex.Message; content += " " + DateTime.Now.ToString() + "-----" + ex.StackTrace; content += " -----z----- "; write.WriteLine(content); //关闭并销毁流写入文件 write.Close(); write.Dispose(); } } } } }
//初稿2-优化-使用微软提供的读写锁:
//读写锁,当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 private static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim(); /// <summary> /// 写入日志. /// </summary> /// <param name="strList">The STR list.</param> /// <remarks> </remarks> /// <Description></Description> public static void WriteLog(params object[] strList) { if (strList.Count() == 0) return; string strPath = ""; //文件路径 try { strPath = strDicPath + string.Format("{0:yyyy年-MM月-dd日}", DateTime.Now) + "日志记录.txt"; } catch (Exception e) { strDicPath = "C:\temp\log\"; strPath = strDicPath + string.Format("{0:yyyy年-MM月-dd日}", DateTime.Now) + "日志记录.txt"; } try { //todo:自动创建文件(但不能创建文件夹),并设置文件内容追加模式,使用using会自动释放FileSteam资源 LogWriteLock.EnterWriteLock(); using (FileStream stream = new FileStream(strPath, FileMode.Append)) { StreamWriter write = new StreamWriter(stream); string content = ""; foreach (var str in strList) { content += " " + DateTime.Now.ToString() + "-----" + str; } content += " -----z----- "; write.WriteLine(content); //关闭并销毁流写入文件 write.Close(); write.Dispose(); } } catch (Exception) { } finally { LogWriteLock.ExitWriteLock(); } }