2017-08-22 1 views
-1

Le code que j'ai inclus ci-dessous écrit avec succès dans un fichier CSV. Mais si le fichier CSV dans lequel j'écris est ouvert dans Excel, j'obtiens un System.IO.Exception qui indique que "le fichier est utilisé par un autre processus".Éviter "fichier utilisé par un autre processus" Exception d'E/S

Comment puis-je modifier mon code pour que le programme continue à fonctionner et attendre que le fichier CSV ne soit plus ouvert dans Excel?

private void timer1_Tick(object sender, EventArgs e) 
    { 
     int actmonth, actyear, actsecond; 
     System.DateTime fecha = System.DateTime.Now; 
     actmonth = fecha.Month; 
     actyear = fecha.Year; 
     if (actmonth <= 9) 
     { 
      valorfechaact = System.Convert.ToString(actyear) + "00" + System.Convert.ToString(actmonth); 
     } 
     else 
     { 
      valorfechaact = System.Convert.ToString(actyear) + "0" + System.Convert.ToString(actmonth); 
     } 

     actsecond = fecha.Second; 

     string label; 
     label = label1.Text; 
     string at = "@"; 
     string filename = valorfechaact + ".csv"; 

     string ruta3 = System.IO.Path.Combine(at, label, filename); 
     if (Directory.Exists(label1.Text)) 
     { 
      StreamWriter wr = new StreamWriter(ruta3, true); 
      wr.WriteLine("1asd" + actsecond); 
      wr.Close(); 
      wr.Dispose(); 
     } 
     else 
     { 
      System.Console.WriteLine("no se puede escribir en el archivo"); 
      timer1.Stop(); 
     } 
    } 
+3

Vous ne pouvez pas écraser le fichier si son ouverture d'Excel comme Excel verrouiller. Vous pouvez toujours réécrire le fichier avec un nom unique si vous rencontrez l'erreur d'E/S. –

+0

@AlexK. Merci pour votre réponse rapide, comment puis-je faire cela? –

+2

essayer/attraper sur cette exception? –

Répondre

1

Vous pouvez écrire un Methode qui essayez d'ouvrir le fichier avec un FileStream et retourner un drapeau booléen

Une solution possible est

public static class FileInfoExtension 
{ 
    public static bool IsLocked(this FileInfo file) 
    { 
     FileStream stream = null; 
     try 
     { 
      stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None); 
     } 
     catch (IOException) 
     { 
      return true; 
     } 
     finally 
     { 
      stream?.Close(); 
     } 
     return false; 
    } 
} 

Ensuite, vous pouvez l'utiliser

var fileInfo = new FileInfo(ruta3); 
    if (!fileInfo.IsLocked()) 
    { 
     // do code 
    } 

Une solution très simple (et mauvaise) à attendre est

while (file.IsLocked()) 
    { 
     Thread.Sleep(100); 
    } 

Général est votre code peu clair et difficile à lire.

Vous avez beaucoup de code redudant et peu de variables sont mal nommées. Peut-être que ce DIRECTRICE peut vous aider https://github.com/dennisdoomen/CSharpGuidelines

Peut-être un peu plus claire solution est

private void timer1_Tick(object sender, EventArgs e) 
    { 
     var directory = label1.Text; 
     if (!Directory.Exists(directory)) 
     { 
      Console.WriteLine("no se puede escribir en el archivo"); 
      timer1.Stop(); 
      return; 
     } 
     var now = DateTime.Now; 
     _valorfechaact = now.Month <= 9 ? $"{now.Year}00{now.Month}" : $"{now.Year}0{now.Month}"; 
     var fullname = Path.Combine("@", directory, $"{_valorfechaact}.csv"); 
     var fileInfo = new FileInfo(fullname); 
     if (fileInfo.IsLocked()) 
     { 
      Console.WriteLine($"The File {fullname} is locked!"); 
      return; 
     } 
     using (var wr = new StreamWriter(fullname, true)) 
     { 
      wr.WriteLine("1asd" + now.Second); 
     } 
    } 
1

Vous pouvez jeter un oeil à cette question:

Checking if an Excel Workbook is open

L'une des approches qui sont discutées est de simplement tenter d'accéder au fichier. Si cela déclenche une exception, vous pouvez attendre et réessayer.

Si vous voulez vraiment attendre jusqu'à ce que le classeur soit accessible en écriture, vous pouvez le faire, par ex. en utilisant une boucle while (vous aurez probablement besoin d'ajouter un timeout, ou si nécessaire, alerter l'utilisateur qu'il doit fermer le fichier dans Excel). Dans le code, il pourrait être quelque chose comme:

int someLargeNumberOfIterations = 100000000; 

while(FileIsLocked(filepath) && elapsedMs < timeoutMs) { 
    Thread.SpinWait(someLargeNumberOfIterations); 

    // Set elapsed 
} 

// Write the file 

où FileIsLocked est une fonction d'écriture basé sur le poste mentionné ci-dessus et un certain délai d'attente est timeoutms approprié.