【问题标题】:IOException caused by file being in use文件正在使用导致的 IOException
【发布时间】:2017-02-08 21:39:16
【问题描述】:

我知道人们已经在这里问过一个问题,但我尝试了他们带来的解决方案,但没有帮助。

我的问题:我正在用 C# 编写一个有 2 种形式的程序。我的主窗体用于读取文件 .txt 并将信息放在 DataGridView 中:

public void LireFichier()
    {
        DataGridView dataGridView1 = new DataGridView();

        string delimeter = ";";
        string tableName = "Clients";
        string filePath = @"C:...\Clients.txt";

        DataSet dataset = new DataSet();

        using (StreamReader sr = new StreamReader(filePath))
        {
            dataset.Tables.Add(tableName);
            dataset.Tables[tableName].Columns.Add("ID");
            dataset.Tables[tableName].Columns.Add("Name");
            dataset.Tables[tableName].Columns.Add("LastName");
            dataset.Tables[tableName].Columns.Add("Datet");
            dataset.Tables[tableName].Columns.Add("Price");
            dataset.Tables[tableName].Columns.Add("Phone");
            dataset.Tables[tableName].Columns.Add("ID box");

            string allData = sr.ReadToEnd();
            string[] rows = allData.Split("\r".ToCharArray());

            foreach (string r in rows)
            {
                string[] items = r.Split(delimeter.ToCharArray());
                dataset.Tables[tableName].Rows.Add(items);
            }
            this.dataGridView1.DataSource = dataset.Tables[0].DefaultView;
         }

我的第二个表单用于在我的 .txt 文件中添加一个客户端:

      private void btn_Confirmer_Click(object sender, EventArgs e)
      {
        string filePath = @"...\Clients.txt";
        Client client = new Client();

        client.Id = idClient++;
        client.Name = tb_name.Text;
        client.LastName = tb_lastName.Text;

        client.Date = dtp_date.Value.ToString("dd-MMM-yyyy");
        client.Price = Convert.ToInt32(tb_price.Text);
        client.Phone = tb_telephone.Text;
        client.ID_Box = Convert.ToInt32(tb_idbox.Text);

        string clientInfo = client.Id.ToString() + ";" + client.Name.ToString() + ";" + client.LastName.ToString() + ";" + client.Date.ToString() + ";" +
                            client.Montant.ToString() + ";" + client.Phone.ToString() + ";" + client.ID_Boc.ToString() + ";";

        using (StreamReader sr = new StreamReader(filePath))
        {
            string allData = sr.ReadToEnd() + clientInfo;
            File.WriteAllText(filePath, allData);
        }

        this.Close();
      }

问题仍然存在于 StreamReader 或 File.WriteAllText 无论我做什么我总是遇到相同的异常(System.IO.IOException),当我到达写入(添加客户端)时,我的文件正在使用以我的第二种形式提交。

我尝试的解决方案是:

  1. 放置 using 块
  2. sr.Close()
  3. sr.Dispose() 即使我知道 using 块调用 dispose 在最后。
  4. sr.Close() 和 sr.Dispose() 在指令的末尾。

【问题讨论】:

  • 这些块是否有可能同时运行?我的意思是当文件为红色时,尝试写入,这导致抛出异常
  • 首先给我们实际的异常文本
  • 我所做的是调用函数 ReadFile();在我的公共 form1(){} 之前 InitializeComponent();我在哪里读取我的文件然后关闭我的文件(至少我试图关闭)并且我有另一个 button_click 打开我的第二个表单,我可以在其中添加一个客户端
  • 我的例外是法语我尝试翻译;在 mscorlib.dll 中遇到了未处理的异常“System.IO.IOException”更多信息:进程无法访问文件“C:\Users\Emmanuel\Desktop\GestionClientPix\GestionClientPix\Clients.txt”,因为它是已经用过了。
  • 请在您的代码中注明异常发生的位置。

标签: c# datagridview


【解决方案1】:

尝试更改为以下内容,因为我认为写入干扰了您已经执行的读取。

string allData; 
using (StreamReader sr = new StreamReader(filePath))
{
    allData = sr.ReadToEnd() + clientInfo;
}

this.Close();
File.WriteAllText(filePath, allData);

【讨论】:

  • allData 定义在using 块的范围内,不能在外面使用
  • 是的,我看到得太晚了,但是代码块的编辑很有趣:p 它应该在使用之前声明 allData,但是无论出于何种原因,代码块都不会显示该行。它去了......有点。
  • 好的,我试过你的代码,我可以完全按照你在原始帖子中的描述重现异常。当我尝试更改时,问题已解决。我同意 Alexi 关于处理异常的方式,并且您只需将客户端信息附加到文件中,无需全部重写。
  • 是的,我在我的程序上试过,它解决了问题,谢谢!
  • 请改用File.AppendText(path, text)。 (或变体)
【解决方案2】:

Trelly 表示问题的最可能原因(文件已在使用中)。但是,包含异常处理的解决方案应该是这样的:

try 
{
    string allData = null; 
    using (var sr = new StreamReader(filePath))
    {
        allData = sr.ReadToEnd() + clientInfo;
    }

    File.WriteAllText(filePath, allData);
}
catch (IOException exc)
{
    // exception handling code
}

this.Close();

您似乎只想在文件末尾附加一些文本。 File.AppendText是你的朋友:

using (StreamWriter sw = File.AppendText(filePath)) 
{
    sw.Write(clientInfo);
}

【讨论】:

  • 谢谢!我在使用 AppendText 时没有出现错误,这意味着问题出在我对同一个文件使用 2 个流式阅读器时
【解决方案3】:

要使您的代码块thread safe,我会使用lock 语句。 首先声明对象,您将执行锁定:

public static readonly Object Locker = new Object();

然后围绕您正在使用 lock 语句的文件的部分代码:

lock(Locker)
{
   //perform file operations
}

请记住,两种形式都必须引用同一个 Locker 对象

【讨论】:

    【解决方案4】:

    ReadToEnd 之后,WriteAllText 之前关闭 StreamReader:

    using (StreamReader sr = new StreamReader(filePath))
    {
        string allData = sr.ReadToEnd() + clientInfo;
        sr.Close() ; // <---- add this instruction
        File.WriteAllText(filePath, allData);
    }
    

    【讨论】:

      猜你喜欢
      • 2012-03-28
      • 1970-01-01
      • 2012-08-05
      • 1970-01-01
      • 2021-01-01
      • 2013-08-06
      • 2021-02-27
      • 1970-01-01
      • 2016-12-24
      相关资源
      最近更新 更多