写入文件时避免访问被拒绝
Avoid Access Denied when writing to file
我正在使用以下方法登录到文件
public static void LogDataContractToFile(string XMLStringToLog, string filePathAndName)
{
FileInfo fileinfoMaster;
FileInfo fileinfoLog;
string fileName = string.Empty;
int tmpInt = 0;
filePathAndName = filePathAndName.ToLower();
while (true)
{
lock (LogDataContractToFileLock)
{
if (!_workingWithFiles.Contains(filePathAndName))
{
_workingWithFiles.Add(filePathAndName);
break;
}
}
Thread.Sleep(100);
}
try
{
#region Create XMLFile
if ((tmpInt = filePathAndName.LastIndexOf('.')) > 0)
fileName = filePathAndName.Remove(tmpInt, filePathAndName.Length - tmpInt);
else
fileName = filePathAndName;
fileinfoMaster = new FileInfo(fileName + ".xml");
fileinfoLog = new FileInfo(fileinfoMaster.DirectoryName + "\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
if ((fileinfoMaster.Exists && !fileinfoLog.Exists) ||
(!fileinfoMaster.Exists && fileinfoLog.Exists))
{
fileinfoMaster.Delete();
fileinfoLog.Delete();
}
//Se så att filen är 50 MB eller mindre annars arkivera
if (fileinfoMaster.Exists && fileinfoLog.Length > 52428800)
{
tmpInt = FileWriter.FileCount(fileinfoLog.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + "*.log");
fileinfoLog.MoveTo(Path.Combine(fileinfoLog.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoLog.Name) + "_" + tmpInt.ToString() + ".log"));
CreateLogDataMasterFile(Path.Combine(fileinfoMaster.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + "_" + tmpInt.ToString() + ".xml"), fileinfoLog.Name);
fileinfoLog = new FileInfo(fileinfoMaster.DirectoryName + "\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
}
if (!fileinfoMaster.Exists)
{
DirectoryInfo info = new DirectoryInfo(fileinfoMaster.DirectoryName);
if (info.Exists == false)
info.Create();
CreateLogDataMasterFile(fileinfoMaster.FullName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
}
#endregion
using (StreamWriter sw = File.AppendText(fileinfoMaster.DirectoryName + "\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log"))
{
sw.Write(XMLStringToLog);
sw.Flush();
}
}
finally
{
lock (LogDataContractToFileLock)
{
_workingWithFiles.Remove(filePathAndName);
}
}
}
private static void CreateLogDataMasterFile(string filepathAndName, string dataFileName)
{
XmlTextWriter xmlWriter;
using (xmlWriter = new XmlTextWriter(filepathAndName, System.Text.Encoding.UTF8))
{
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlWriter.WriteDocType("DataLog", null, null, "<!ENTITY data SYSTEM \"" + dataFileName + "\">");
xmlWriter.WriteStartElement("root");
xmlWriter.WriteRaw("&data;");
xmlWriter.WriteEndElement();
xmlWriter.Flush();
}
}
几个不同的线程可能会同时写入文件,在某些情况下,它们会写入同一个文件。为了避免 access denied, used by other process
出现问题,我已经实现了一些逻辑,如您所见。
问题是我仍然不时收到 access denied, used by other process
。
我查看了 TextWriterTraceListener 和 here 等内置跟踪器,我可以看到以下注释:
If an attempt is made to write to a file that is in use or
unavailable, the file name is automatically prefixed by a GUID.
这么看来连微软也有这方面的问题?是 Windows 问题吗?除了生成新文件之外,有什么办法可以处理这个问题吗?生成新文件会使文件中的数据流混乱很多!
是的。不要从多个线程写入文件。创建一个负责文件写入的线程,并让它从 ConcurrentQueue 中读取要写入的内容。任何需要写入的线程都应该将数据添加到队列中。
我正在使用以下方法登录到文件
public static void LogDataContractToFile(string XMLStringToLog, string filePathAndName)
{
FileInfo fileinfoMaster;
FileInfo fileinfoLog;
string fileName = string.Empty;
int tmpInt = 0;
filePathAndName = filePathAndName.ToLower();
while (true)
{
lock (LogDataContractToFileLock)
{
if (!_workingWithFiles.Contains(filePathAndName))
{
_workingWithFiles.Add(filePathAndName);
break;
}
}
Thread.Sleep(100);
}
try
{
#region Create XMLFile
if ((tmpInt = filePathAndName.LastIndexOf('.')) > 0)
fileName = filePathAndName.Remove(tmpInt, filePathAndName.Length - tmpInt);
else
fileName = filePathAndName;
fileinfoMaster = new FileInfo(fileName + ".xml");
fileinfoLog = new FileInfo(fileinfoMaster.DirectoryName + "\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
if ((fileinfoMaster.Exists && !fileinfoLog.Exists) ||
(!fileinfoMaster.Exists && fileinfoLog.Exists))
{
fileinfoMaster.Delete();
fileinfoLog.Delete();
}
//Se så att filen är 50 MB eller mindre annars arkivera
if (fileinfoMaster.Exists && fileinfoLog.Length > 52428800)
{
tmpInt = FileWriter.FileCount(fileinfoLog.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + "*.log");
fileinfoLog.MoveTo(Path.Combine(fileinfoLog.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoLog.Name) + "_" + tmpInt.ToString() + ".log"));
CreateLogDataMasterFile(Path.Combine(fileinfoMaster.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + "_" + tmpInt.ToString() + ".xml"), fileinfoLog.Name);
fileinfoLog = new FileInfo(fileinfoMaster.DirectoryName + "\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
}
if (!fileinfoMaster.Exists)
{
DirectoryInfo info = new DirectoryInfo(fileinfoMaster.DirectoryName);
if (info.Exists == false)
info.Create();
CreateLogDataMasterFile(fileinfoMaster.FullName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
}
#endregion
using (StreamWriter sw = File.AppendText(fileinfoMaster.DirectoryName + "\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log"))
{
sw.Write(XMLStringToLog);
sw.Flush();
}
}
finally
{
lock (LogDataContractToFileLock)
{
_workingWithFiles.Remove(filePathAndName);
}
}
}
private static void CreateLogDataMasterFile(string filepathAndName, string dataFileName)
{
XmlTextWriter xmlWriter;
using (xmlWriter = new XmlTextWriter(filepathAndName, System.Text.Encoding.UTF8))
{
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlWriter.WriteDocType("DataLog", null, null, "<!ENTITY data SYSTEM \"" + dataFileName + "\">");
xmlWriter.WriteStartElement("root");
xmlWriter.WriteRaw("&data;");
xmlWriter.WriteEndElement();
xmlWriter.Flush();
}
}
几个不同的线程可能会同时写入文件,在某些情况下,它们会写入同一个文件。为了避免 access denied, used by other process
出现问题,我已经实现了一些逻辑,如您所见。
问题是我仍然不时收到 access denied, used by other process
。
我查看了 TextWriterTraceListener 和 here 等内置跟踪器,我可以看到以下注释:
If an attempt is made to write to a file that is in use or unavailable, the file name is automatically prefixed by a GUID.
这么看来连微软也有这方面的问题?是 Windows 问题吗?除了生成新文件之外,有什么办法可以处理这个问题吗?生成新文件会使文件中的数据流混乱很多!
是的。不要从多个线程写入文件。创建一个负责文件写入的线程,并让它从 ConcurrentQueue 中读取要写入的内容。任何需要写入的线程都应该将数据添加到队列中。