C#无法访问该文件,因为它被其他进程使用

时间:2012-08-23 08:18:44

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

我有将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未正确关闭,因此

未关闭,或者因为发送电子邮件正在使用此文件而

5 个答案:

答案 0 :(得分:1)

假设您输入此代码不止一次 在任何一种情况下,您都需要调用MailMsg.Dispose()类的MailMessage。 否则,它会保留附件,导致下次尝试写入文件时锁定文件。

尝试在MailMessage上使用using语句

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

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

答案 1 :(得分:0)

那是因为你的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,因此这可能是一个因素。

答案 2 :(得分:0)

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

StreamWriter sw;
try
{
   sw = new StreamWriter(strFilePath, false);
}
Catch
{

}
finally
{
 sw.Flush();
 sw.Close();
 sw.Dispose();
}

答案 3 :(得分:0)

在您的最后一段代码中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 :(得分:0)

所以,看起来你的第一个attemopt是合理的(总结如下)

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