我的程序是为我练习的,但是,当我尝试编写它找到的所有目录时,它会崩溃。
我尝试了以下内容:
我不明白为什么这不起作用,我做错了什么?
static void Main(string[] args)
{
Method(@"C:\");
}
static void Method(string dir)
{
//crash happens here v
StreamWriter sw = new StreamWriter(@"C:\users\"+Environment.UserName+"\desktop\log.txt",true);
foreach (string subdir in Directory.GetDirectories(dir))
{
try
{
Console.WriteLine(subdir);
sw.Write(subdir);
Method(subdir);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Error");
}
}
sw.Close();
}
答案 0 :(得分:4)
它的递归。
因为您在此处再次致电Method
:
Console.WriteLine(subdir);
sw.Write(subdir);
Method(subdir); // BOOM
您的文件已经打开。你不能再打开它了。
在Main
中打开文件一次..
static void Main(string[] args) {
using (StreamWriter sw = new StreamWriter(@"C:\users\"+Environment.UserName+"\desktop\log.txt",true)) {
Method(@"C:\", sw);
}
}
然后在你的方法中接受它:
public static void Method(string dir, StreamWriter sw) {
然后当你再次打电话时:
sw.Write(subdir);
Method(subdir, sw); // pass in the streamwriter.
但请注意,您将很快开始咀嚼内存。您正在通过整个C:\驱动器进行递归。也许在较小的文件夹上测试它?
答案 1 :(得分:2)
在您再次使用之前,似乎没有关闭您的编写器
public static void Method(string dir)
{
//crash happens here v
StreamWriter sw = new StreamWriter(@"C:\users\"+Environment.UserName+"\desktop\log.txt",true);
foreach (string subdir in Directory.GetDirectories(dir))
{
try
{
Console.WriteLine(subdir);
sw.Write(subdir);
//This line you'll call "Method" again
Method(subdir);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Error");
}
}
sw.Close();
}
另外,另一个建议是,为什么不使用“System.IO.File.AppendAllText(Path,Text)”方法?它更容易使用
答案 2 :(得分:1)
我同意以上内容,但就我而言,解决方案略有不同。
private static object locker = new object();
private static void WriteMessageToFile(string message)
{
string dateStr = DateTime.Now.Date.Day.ToString()+"_"+ DateTime.Now.Date.Month.ToString()+"_"+ DateTime.Now.Date.Year.ToString();
if (!Directory.Exists("Logs"))
{
DirectoryInfo di = Directory.CreateDirectory("Logs");
}
//Guid guidGenerator = Guid.NewGuid();
string filePath = _env.ContentRootPath + "\\Logs\\ProcessLog_" + dateStr + ".txt";
FileInfo fi = new FileInfo(filePath);
lock (locker)
{
using (FileStream file = new FileStream(fi.FullName, FileMode.Append, FileAccess.Write, FileShare.Read))
using (StreamWriter streamWriter = new StreamWriter(file))
{
streamWriter.WriteLine(message);
streamWriter.Close();
}
}
}
因为在我的asp.net核心应用程序中,以下功能在许多地方都称为异步和异步。在这种情况下,一个线程试图写入文件,另一个线程想要写入同一文件,并且发生错误。作为解决方案,我尝试了上面的方法,但是由于我试图在关闭上一个流之前先打开一个新的流,所以它也不起作用。因此,我决定编写一个安全的代码块作为解决方案。在这种情况下,由于其他线程无法到达锁定区域,因此它们通过等待上一个操作来进行写入操作,因此我能够无错误地写入文件。
我认为;背后还有另一个原因代码,原因是我在启动时使用了Singleton注册。该函数的调用程序类相互隔离。因此,他们之前不知道哪个线程被称为函数。他们的一生已经结束了。 FileStream还包装了StreamWriter,然后它也可以在没有锁的情况下工作,无论如何保证。
即使Microsoft.Extensions.Logging默认也不支持FileLoger,但我们可以编写自定义。我在下面分享了整个实现
public class FileLoger : ILogger
{
public static IHostingEnvironment _env;
private static object locker = new object();
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
var message = string.Format("{0}: {1} - {2}", logLevel.ToString(), eventId.Id, formatter(state, exception));
WriteMessageToFile(message);
}
private static void WriteMessageToFile(string message)
{
string dateStr = DateTime.Now.Date.Day.ToString()+"_"+ DateTime.Now.Date.Month.ToString()+"_"+ DateTime.Now.Date.Year.ToString();
if (!Directory.Exists("Logs"))
{
DirectoryInfo di = Directory.CreateDirectory("Logs");
}
//Guid guidGenerator = Guid.NewGuid();
string filePath = _env.ContentRootPath + "\\Logs\\ProcessLog_" + dateStr + ".txt";
FileInfo fi = new FileInfo(filePath);
lock (locker)
{
using (FileStream file = new FileStream(fi.FullName, FileMode.Append, FileAccess.Write, FileShare.Read))
using (StreamWriter streamWriter = new StreamWriter(file))
{
streamWriter.WriteLine(message);
streamWriter.Close();
}
}
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
}
public class FileLogProvider : ILoggerProvider
{
public FileLogProvider(IHostingEnvironment env)
{
FileLoger._env = env;
}
public ILogger CreateLogger(string category)
{
return new FileLoger();
}
public void Dispose()
{
}
}