在独占打开的文件中追加文本
本文关键字:文件 追加 文本 | 更新日期: 2023-09-27 18:03:52
我正在尝试实现锁定场景,其中同一文件被多个线程在同一时间或不同时间访问。在测试时,代码似乎覆盖了现有的行,而不是附加新的行。
namespace SMPPService
{
public static class LogFile
{
public static void WriteErrorLog(Exception ex)
{
byte[] buf = GetBytes(DateTime.Now.ToString() + ": " + ex.Source.ToString().Trim() + "; " + ex.Message.ToString().Trim());
Lock(HttpRuntime.AppDomainAppPath + "''Exceptions.txt",
(f) =>
{
try
{
f.Write(buf, 0, buf.Length);
}
catch (IOException ioe)
{
// handle IOException
}
}, buf);
}
public static void WriteErrorLog(string Message)
{
byte[] buf = GetBytes(DateTime.Now.ToString() + ": " + Message);
Lock(HttpRuntime.AppDomainAppPath + "''LogFile.txt",
(f) =>
{
try
{
f.Write(buf, 0, buf.Length);
}
catch (IOException ioe)
{
// handle IOException
}
}, buf);
System.Threading.Thread.Sleep(60000);
}
public static void Lock(string path, Action<FileStream> action,byte [] lines)
{
var autoResetEvent = new AutoResetEvent(false);
while (true)
{
try
{
using (var file = File.Open(path,
FileMode.OpenOrCreate,
FileAccess.ReadWrite,
FileShare.Write))
{
action(file);
break;
}
}
catch (IOException)
{
var fileSystemWatcher =
new FileSystemWatcher(Path.GetDirectoryName(path))
{
EnableRaisingEvents = true
};
fileSystemWatcher.Changed +=
(o, e) =>
{
if (Path.GetFullPath(e.FullPath) == Path.GetFullPath(path))
{
autoResetEvent.Set();
}
};
autoResetEvent.WaitOne();
}
}
}
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
}
}
使用LogFile.WriteErrorLog("Requesting SMPP Client from WMAS..." + " " + "Date:" + DateTime.Now + " " + "Source Address:" + msisdn);
FileShare.Write
从MSDN: 允许后续打开文件进行写入。
这正是您不想使用的标志。对于文件,最简单的锁定方法是让文件系统为您锁定,使用FileShare.Read
(以便有人可以查看日志),如果由于共享违规而打开失败,则重试。
像这样实现你自己的锁只会在文件系统已经有锁的情况下重新创建,而且很糟糕。
另外,不要自己处理编码(正确处理边缘情况并不容易):
- 以指定编码(UTF-8将是我的选择)的文本文件打开。
- 打开附加的文件,这样新内容总是写在末尾。
有一个重载StreanWriter
的构造函数来做这个。
FileShare.Read
。
您应该使用File。AppendAllLines代替lock
方法。文件。AppendAllLines 不是线程安全的,你必须锁定它。
private object lockObject = new object();
private string fileName = Path.Combine(HttpRuntime.AppDomainAppPath, "LogFile.txt");
public static void WriteErrorLog(string Message)
{
lock(lockObject)
{
File.AppendAllLines(fileName, new string[] { Message + "'n" });
}
}
注意文件。AppendAllLines是在。net 4中引入的,你必须使用File。旧框架中的AppendAllText