【问题标题】:C# cannot access the file, because it used by other processC# 无法访问该文件,因为它被其他进程使用
【发布时间】:2012-08-18 17:23:37
【问题描述】:

我有将 SQL 转换为 CSV 的代码:

public void CreateCSVFile(DataTable dt, string strFilePath, bool Is_Ordre, int TypeDonne)
{

    //FileStream fs = new FileStream(strFilePath, FileMode.Create);
    // FileStream fs = File.Create(strFilePath);

    // Create the CSV file to which grid data will be exported.
    //StreamWriter sw = new StreamWriter(fs);
    //StreamWriter sw = new StreamWriter(strFilePath, false);
    using (var sw = new StreamWriter(strFilePath, false))
    {
        // First we will write the headers.
        //DataTable dt = m_dsProducts.Tables[0];
        int iColCount = dt.Columns.Count;
        for (int i = 0; i < iColCount; i++)
        {
            sw.Write(dt.Columns[i]);
            if (i < iColCount - 1)
            {
                sw.Write(",");
            }
        }
        if (Is_Ordre) sw.Write(", TYP_DONNE");

        sw.Write(sw.NewLine);

        // Now write all the rows.
        foreach (DataRow dr in dt.Rows)
        {
            for (int i = 0; i < iColCount; i++)
            {
                if (!Convert.IsDBNull(dr[i]))
                {
                    sw.Write("\'" + dr[i].ToString().Replace("'", " ").Replace(",", ".") + "\'");
                }
                else
                {
                    sw.Write("\' \'");
                }
                if (i < iColCount - 1)
                {
                    sw.Write(",");
                }
            }
            if (Is_Ordre) sw.Write(", \'" + TypeDonne + "\'");
            sw.Write(sw.NewLine);
        }                
        sw.Flush();
        sw.Close();
        sw.Dispose();
    }
        //fs.Close();

}

之后我通过电子邮件发送 CSV 文件:

Attachment data_OD = new Attachment(LeSource, MediaTypeNames.Application.Octet);
Attachment data_LV = new Attachment(LeSource_LV, MediaTypeNames.Application.Octet);
oEmail.SendingEmail(ClientID,  data_OD, data_LV);

public void SendingEmail(string CodeClient, Attachment dataOD, Attachment dataLV)
{
    try
    {
        Pers_Conf oConf = LeConf.Get_Config(CodeClient);

        MailMessage omail = new MailMessage();
        var oSmtp = new SmtpClient("smtp.gmail.com", 587)
        {
            Credentials = new NetworkCredential("xxxxxx@gmail.com", "xxxxxx"),
            EnableSsl = true
        };

        omail.From = new MailAddress("xxxxx@gmail.com");               
        omail.To.Add(oConf.EmailAddr);
        omail.Subject = "xxxxxx_" + CodeClient;
        omail.Body = CodeClient;

        omail.Attachments.Add(dataOD);
        omail.Attachments.Add(dataLV);

        oSmtp.Send(omail);
    }
    catch (Exception excThrown)
    {
        throw excThrown;
    }

StreamWriter 似乎没有正确关闭文件,我已经尝试过:

    Try
    {
    StreamWriter sw = new StreamWriter(strFilePath, false);
    }
    Catch
    {
    }
    Finaly
    {
     sw.Flush();
     sw.Close();
     sw.Dispose();
}

但在finally 块中它无法识别sw

有什么想法吗?

PS:这行代码抛出一个异常,表明该文件正在被其他进程使用

 using (var sw = new StreamWriter(strFilePath, false))

没有关闭是因为StreamWriter没有正确关闭或者是因为发送电子邮件正在使用这个文件?

【问题讨论】:

  • 您能否更具体地说明您在哪一行得到了异常?初次使用?
  • 这发生在程序第一次访问该函数时,或者整个过程(构建、发送)以相同的文件名重复多次?
  • 它发生在程序第二次访问此功能时

标签: c# sql-server-2008 streamwriter export-to-csv


【解决方案1】:

假设您多次输入此代码。
无论哪种情况,您都需要调用MailMessage 类的MailMsg.Dispose()。 否则,它将保留附件,从而在您下次尝试写入时锁定文件。

尝试在 MailMessage 上也使用 using 语句

        try 
        { 
            Pers_Conf oConf = LeConf.Get_Config(CodeClient); 

            using(MailMessage omail = new MailMessage())
            {
                .....
                oSmtp.Send(omail); 
            }
        } 
        catch (Exception excThrown) 
        { 
            throw excThrown; 
        } 

【讨论】:

    【解决方案2】:

    StreamWriter 将超出范围。如果你折射到以下...

    StreamWriter sw;
    try
    {
       sw = new StreamWriter(strFilePath, false);
    }
    Catch
    {
    
    }
    finally
    {
     sw.Flush();
     sw.Close();
     sw.Dispose();
    }
    

    【讨论】:

      【解决方案3】:

      在您的最后一个代码块中,sw 无法识别,因为它超出了范围。

      请试试这个:

       StreamWriter sw;
      
       try
       {
          sw = new StreamWriter(strFilePath, false);
       }
       catch
       {
          // Never do an empty catch BTW!    
       }
       finally
       {
         if (sw != null)
         {
           sw.Flush();
           sw.Close();
           sw.Dispose();
         }
      }
      

      或者更好的是,使用 using 语句:

      using (StreamWriter sw = new StreamWriter(strFilePath, false))
      {
          // Just do your thing, at the end sw will be cleaned up for you :)
      }
      

      【讨论】:

        【解决方案4】:

        那是因为您的 StreamWriter 声明超出范围,请尝试以下操作:

        using (StreamWriter sw = new StreamWriter(strFilePath, false))
        {
        }
        

        这将在编译时为您添加tryfinally 代码。或者,如果您想自己指定 try 块,请执行以下操作:

        StreamWriter sw;
        
        try
        {
            sw = new StreamWriter(strFilePath, false);
        }
        catch
        {
        }
        finally
        {
            sw.Flush();
            sw.Close();
            sw.Dispose();        
        }
        

        这会将其范围赋予finally

        编辑

        您可以尝试将 using 块添加到文件流中以创建文件,然后使用 StreamWriter 写入此流,正如 Darin 指出的那样,您已经这样做了。

        using (FileStream fs = new FileStream(strFilePath, FileMode.Create, FileAccess.Write))
        {
            using (StreamWriter sw = new StreamWriter(fs))
            {
                // write your content
        
                sw.Flush();
                sw.Close();
            }
        
            fs.Close();
        }
        

        如果您使用代码中的File.Create 创建文件(但它已被注释掉),那么您并没有关闭您的FileStream,因此这可能是一个因素。

        【讨论】:

        • 这是他目前拥有的。再次查看他的代码,在 CreateCSVFile 方法中。
        • @DarinDimitrov:是的,这有点懒惰,我只抓住了最后一部分,假设这是他的问题。
        【解决方案5】:

        所以,看起来你的第一次尝试是合理的(总结如下)

        using (var sw = new StreamWriter(strFilePath, false)) 
        { 
            sw.Flush();  
            sw.Close();  
            sw.Dispose();  
        }
        

        虽然不需要 sw..Dispose(),因为它位于 using{} 块中。

        那么您看到的具体问题是什么?

        好的,我刚刚看到您的编辑。你确定它不是锁定文件的其他东西,可能是附件。我看不到这是在什么范围内声明的,但它有可能挂在文件上吗?如果你想检查是什么锁定了它,你可以使用 ProcessMonitor...

        http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-01-17
          • 1970-01-01
          • 2013-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多