【问题标题】:C# The process cannot access the file ''' because it is being used by another processC#进程无法访问文件''',因为它正被另一个进程使用
【发布时间】:2011-04-17 18:20:46
【问题描述】:

代码的 sn-p 只是应该将一个字符串写入一个名为“all_results.txt”的文本文件中。我在 File.WriteAllText 中实现错误。在网上搜索解决方案后,我尝试使用 FileStream 和 StreamWriter 作为替代品。问题仍然存在。

它给了我:

IOException Unhandled:进程无法访问文件 'C:\Users\MadDebater\Desktop\ConsoleTest1\ConsoleTest\bin\Debug\all_results.txt',因为它正被另一个进程使用。

奇怪的是,错误是任意发生的。它可能在第 3 次循环或第 45 次循环期间发生错误。我提供了该类的完整代码,以防问题比看起来更深。我确定这与我的病毒扫描程序或类似的东西无关。

try
                {
                    using (FileStream stream = new FileStream(@"all_results.txt", FileMode.Create)) // Exception here
                {
                    using (StreamWriter writer = new StreamWriter(stream))
                    {
                        writer.WriteLine(result);
                        writer.Dispose();
                        writer.Close();
                    }

                    stream.Dispose();
                    stream.Close();
                }

                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex);
                }

即使我尝试了这个,它仍然失败。

try
                {
                    File.WriteAllText(@"all_results.txt", result); // Exception here
                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex.Message);
                }

以下是该类的完整代码。它旨在获取 Twitter 推文列表,并使用贝叶斯分类对其进行一一分类。

    using System;
    using System.IO;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using BayesClassifier;
    using System.Text.RegularExpressions;

    namespace ConsoleTest
    {
        class Analyzer
        {
            public static void Analyzing(List<string> all_results)
            {

            Reducting(all_results);
            Classifying();
        }

        public static void Reducting(List<string> all_results)
        {
            //Reductor
            //Precondition: List<string> results
            all_results.ForEach(delegate(String text)
            {

                const string ScreenNamePattern = @"@([A-Za-z0-9\-_&;]+)";
                const string HashTagPattern = @"#([A-Za-z0-9\-_&;]+)";
                const string HyperLinkPattern = @"(http://\S+)\s?";
                string result = text;

                if (result.Contains("http://"))
                {
                    var links = new List<string>();
                    foreach (Match match in Regex.Matches(result, HyperLinkPattern))
                    {
                        var url = match.Groups[1].Value;
                        if (!links.Contains(url))
                        {
                            links.Add(url);
                            result = result.Replace(url, String.Format(""));
                        }
                    }
                }

                if (result.Contains("@"))
                {
                    var names = new List<string>();
                    foreach (Match match in Regex.Matches(result, ScreenNamePattern))
                    {
                        var screenName = match.Groups[1].Value;
                        if (!names.Contains(screenName))
                        {
                            names.Add(screenName);
                            result = result.Replace("@" + screenName,
                               String.Format(""));
                        }
                    }
                }

                if (result.Contains("#"))
                {
                    var names = new List<string>();
                    foreach (Match match in Regex.Matches(result, HashTagPattern))
                    {
                        var hashTag = match.Groups[1].Value;
                        if (!names.Contains(hashTag))
                        {
                            names.Add(hashTag);
                            result = result.Replace("#" + hashTag,
                               String.Format(""));
                        }
                    }
                }

                // Write into text file
/*
                try
                {
                    using (FileStream stream = new FileStream(@"all_results.txt", FileMode.Create)) // Exception here
                {
                    using (StreamWriter writer = new StreamWriter(stream))
                    {
                        writer.WriteLine(result);
                        writer.Dispose();
                        writer.Close();
                    }

                    stream.Dispose();
                    stream.Close();
                }

                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex);
                }
                */
                try
                {
                    File.WriteAllText(@"all_results.txt", result); // Exception here
                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex.Message);
                }

            });
        }

        public static void Classifying()
        {
            // Classifying

            BayesClassifier.Classifier m_Classifier = new BayesClassifier.Classifier();


            m_Classifier.TeachCategory("Positive", new System.IO.StreamReader("POSfile.txt"));
            m_Classifier.TeachCategory("Negative", new System.IO.StreamReader("NEGfile.txt"));

            Dictionary<string, double> newscore;
            newscore = m_Classifier.Classify(new System.IO.StreamReader("all_results.txt"));

            PrintResults(newscore);
}

        public static void PrintResults(Dictionary<string, double> newscore)
        {
            foreach (KeyValuePair<string, double> p in newscore)
            {
                Console.WriteLine(p.Key + ", " + p.Value);
            }

            List<string> list = new List<string>();
            using (StreamReader reader = new StreamReader("all_results.txt"))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    list.Add(line);          // Add to list.
                    Console.WriteLine(line); // Write to console.

                }

                reader.Close();
            }

            //PrintSentiment(newscore);
        }

        public static void PrintSentiment(Dictionary<string, double> newscore)
        {

            // if difference < 2, neutral
            // if neg < pos, pos
            // if pos < neg, neg

            double pos = newscore["Positive"];
            double neg = newscore["Negative"];
            string sentiment = "";

            if (Math.Abs(pos - neg) < 1.03)
            {
                sentiment = "NEUTRAL";
            }
            else
            {
                if (neg < pos)
                {
                    sentiment = "POSITIVE";
                }
                else if (pos < neg)
                {
                    sentiment = "NEGATIVE";
                }
            }

            Console.WriteLine(sentiment);


            // append tweet_collection to final_results <string> list
            // append sentiment tag to the final_results <string> list
            // recursive
        }
    }
}

【问题讨论】:

  • 有什么理由不使用 TextWriter?
  • 我过去在紧密循环中写入文本文件时也发现了类似的错误。该文件没有及时发布以供下一次迭代使用,这可能是问题所在,尤其是在要编写大量文本的情况下
  • @w69rdy 不熟悉 TextWriter。有没有解决紧密循环问题的方法?
  • 处理它的最佳方法是保持文件打开,直到您完成写入。这应该可以避免您遇到的问题,并且还会在您尝试使用它时阻止任何其他进程打开。
  • @w69rdy 你能告诉我如何通过代码做到这一点吗?这样就清楚多了。我对文件没有经验。

标签: c# asp.net visual-studio-2010 ioexception


【解决方案1】:

使用类似 filemon 的实用程序来检查哪些进程正在使用该文件。

更新: 从我读到的过程监视器与 filemon 非常相似。从这些工具中的任何一个中,您都可以找到哪个进程在什么时候访问了您的文件。您可以在开始监控之前为您的文件添加过滤器。

您可以尝试的另一件事是锁定文件(如果存在)。

【讨论】:

  • 根据谷歌搜索,Windows 不再支持 Filemon。我尝试了进程监视器,但我不确定如何识别哪个进程正在使用该文件。解释一下?
  • 你想要进程资源管理器。启动它,按 CTRL-F,然后输入文件名的一部分,它会显示与该名称匹配的所有句柄。
  • 知道了!当调试过程中出现错误时,Process Explorer 显示如下: ConsoleTest.vshost.exe (Process) 4372 (PID) Handle (Type) C:\Users\MadDebater\Desktop\ConsoleTest2\ConsoleTest\bin\Debuall_results.txt (Handle or DLL )。接下来我该怎么办?
  • 异常通过时运行这段代码 --> File.WriteAllText(@"all_results.txt", result);
  • 第二次运行,结果是:(进程),3712(PID),Handle(类型),C:\Users\MadDebater\Desktop\ConsoleTest2\ConsoleTest \bin\Debug\all_results.txt(句柄或 DLL)。
【解决方案2】:

可能文件被病毒扫描程序或 Windows 索引服务访问?

【讨论】:

  • 关闭病毒扫描程序、Google 桌面和 Windows 索引服务。没有运气。
【解决方案3】:

尝试将文件写入调试文件夹之外的另一个目录。

【讨论】:

  • 尝试使用 c:/all_results.txt
【解决方案4】:

只是一个“狂野的镜头” - 如果您将文件放在更可预测的位置,例如 'c:\all_results.txt' 会有所帮助吗?

【讨论】:

    【解决方案5】:

    尝试将 Thread.Sleep(1000) 放入您的循环中。就像上面提到的人一样,文件并不总是在循环的下一次迭代中及时发布。

    【讨论】:

      【解决方案6】:

      不要在 FileStream 和 StreamWriter 上调用 Dispose() 和 Close(),这将由 using 子句自动处理。

      【讨论】:

      • 即使我只使用不使用 Dispose() 和 Close() 方法的 File.WriteAllText() 代码,问题仍然存在。
      • StreamReader 也在 PrintResults 方法中手动关闭。尝试不打那个电话。
      • 是否有多个线程?似乎您正在覆盖自己的文件,有时它被自己锁定在另一个线程中。为什么你使用带委托的 ForEach 而不是普通的 foreach(all_results 中的字符串文本)?
      【解决方案7】:

      正如其他人所说,反复打开和关闭文件可能是问题所在。未提及的一种解决方案是在处理期间保持文件打开。完成后,即可关闭文件。

      【讨论】:

      • 你能告诉我如何通过代码来完成吗?这样就清楚多了。
      • 在 foreach 循环之前打开 FileStream。在循环内部调用 .WriteLine()。 foreach 完成后,关闭 FileStream。
      【解决方案8】:

      佩德罗:

      正如其他人所说,反复打开和关闭文件可能是问题所在。未提及的一种解决方案是在处理期间保持文件打开。完成后,即可关闭文件。

      或者,或者,将您的文本收集到 StringBuilder 或其他一些内存文本存储中,然后在循环完成后将文本转储到文件中。

      【讨论】:

      • 不幸的是,贝叶斯分类器将 .txt 文件作为输入,所以我别无选择。倾倒整个东西不会给我一个推特推文的分类。
      • 然后你可以尝试在一个文件上写一条推文,这样就不会有 2 次迭代写入同一个文件。这样做是为了给操作系统足够的时间来关闭文件并释放它的句柄。知道您写入的所有文件名可以让您将它们一一提供给分类器。
      • 关于内存中作为重复文件写入的另一种选择的好点。
      【解决方案9】:

      我在遇到类似问题时找到了该帖子。给定的建议给了我一个想法!所以为此我写了如下方法

      public static void ExecuteWithFailOver(Action toDo, string fileName)
      {
      
          for (var i = 1; i <= MaxAttempts; i++)
          {
              try
              {
                  toDo();
      
                  return;
              }
              catch (IOException ex)
              {
                  Logger.Warn("File IO operation is failed. (File name: {0}, Reason: {1})", fileName, ex.Message);
                  Logger.Warn("Repeat in {0} milliseconds.", i * 500);
      
                  if (i < MaxAttempts)
                      Thread.Sleep(500 * i);
              }
          }
      
          throw new IOException(string.Format(CultureInfo.InvariantCulture,
                                              "Failed to process file. (File name: {0})",
                                              fileName));
      
      }
      

      然后我按照下面的方式使用方法

          Action toDo = () =>
                         {
                             if (File.Exists(fileName))
                                 File.SetAttributes(fileName, FileAttributes.Normal);
      
                             File.WriteAllText(
                                 fileName,
                                 content,
                                 Encoding.UTF8
                                 );
                         };
      
          ExecuteWithFailOver(toDo, fileName);
      

      后来分析日志我发现我的麻烦的原因是试图从并行线程中对同一个文件采取行动。但我仍然看到一些使用建议的故障转移方法的优点

      【讨论】:

        【解决方案10】:

        尝试对文件操作使用锁定。 http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

        【讨论】:

          猜你喜欢
          • 2011-07-05
          • 2016-12-24
          • 2013-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多