web-dev-qa-db-fra.com

System.IO.IOException: fichier utilisé par un autre processus

J'ai travaillé sur ce petit morceau de code qui semble trivial, mais je ne vois toujours pas vraiment où est le problème. Mes fonctions font une chose assez simple. Ouvre un fichier, copie son contenu, remplace une chaîne à l'intérieur et recopie-le dans le fichier d'origine (une simple recherche et remplacement à l'intérieur d'un fichier texte) . Je ne savais pas vraiment comment le faire car je suis ajouter des lignes au fichier original, je crée donc simplement une copie du fichier (fichier.temp), copie également une sauvegarde (fichier.temp), supprime le fichier original (fichier) et copie le fichier.temp dans un fichier .. .J'obtiens une exception lors de la suppression du fichier . Voici l'exemple de code:

private static bool modifyFile(FileInfo file, string extractedMethod, string modifiedMethod)
    {
        Boolean result = false;
        FileStream fs = new FileStream(file.FullName + ".tmp", FileMode.Create, FileAccess.Write);
        StreamWriter sw = new StreamWriter(fs);

        StreamReader streamreader = file.OpenText();
        String originalPath = file.FullName;
        string input = streamreader.ReadToEnd();
        Console.WriteLine("input : {0}", input);

        String tempString = input.Replace(extractedMethod, modifiedMethod);
        Console.WriteLine("replaced String {0}", tempString);

        try
        {
            sw.Write(tempString);
            sw.Flush();
            sw.Close();
            sw.Dispose();
            fs.Close();
            fs.Dispose();
            streamreader.Close();
            streamreader.Dispose();

            File.Copy(originalPath, originalPath + ".old", true);
            FileInfo newFile = new FileInfo(originalPath + ".tmp");
            File.Delete(originalPath);
            File.Copy(fs., originalPath, true);

            result = true;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        return result;
    }`

Et l'exception connexe

System.IO.IOException: The process cannot access the file 'E:\mypath\myFile.cs' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.File.Delete(String path)
   at callingMethod.modifyFile(FileInfo file, String extractedMethod, String modifiedMethod)

Normalement, ces erreurs proviennent de flux de fichiers non fermés, mais je m'en suis occupé. J'imagine que j'ai oublié une étape importante mais je ne peux pas savoir où… .. Merci beaucoup pour votre aide,

25
srodriguez

On dirait qu'un processus externe (AV?) Le verrouille, mais ne pouvez-vous pas éviter le problème en premier lieu?

private static bool modifyFile(FileInfo file, string extractedMethod, string modifiedMethod)
{
    try
    {
        string contents = File.ReadAllText(file.FullName);
        Console.WriteLine("input : {0}", contents);
        contents = contents.Replace(extractedMethod, modifiedMethod);
        Console.WriteLine("replaced String {0}", contents);
        File.WriteAllText(file.FullName, contents);
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
        return false;
    }
}
24
si618

Je me rends compte que je suis un peu en retard, mais qu'il vaut mieux tard que jamais. J'avais un problème similaire récemment. J'ai utilisé XMLWriter pour mettre à jour ultérieurement le fichier XML et recevais les mêmes erreurs. J'ai trouvé la solution propre pour cela:

XMLWriter utilise FileStream sous-jacent pour accéder au fichier modifié. Le problème est que lorsque vous appelez la méthode XMLWriter.Close(), le flux sous-jacent ne se ferme pas et verrouille le fichier. Ce que vous devez faire est d’instancier votre XMLWriter avec des paramètres et de spécifier que vous avez besoin que ce flux sous-jacent soit fermé.

Exemple:

XMLWriterSettings settings = new Settings();
settings.CloseOutput = true;
XMLWriter writer = new XMLWriter(filepath, settings);

J'espère que ça aide.

19
roquen

Le code fonctionne comme je peux le dire. Je voudrais lancer Sysinternals traiter Explorer et découvrir ce qui maintient le fichier ouvert. Ce pourrait très bien être Visual Studio.

5
chris.w.mclean

Cela a fonctionné pour moi.

Voici mon code de test. Le test suit:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            FileInfo f = new FileInfo(args[0]);
            bool result = modifyFile(f, args[1],args[2]);
        }
        private static bool modifyFile(FileInfo file, string extractedMethod, string modifiedMethod) 
        { 
            Boolean result = false; 
            FileStream fs = new FileStream(file.FullName + ".tmp", FileMode.Create, FileAccess.Write); 
            StreamWriter sw = new StreamWriter(fs); 
            StreamReader streamreader = file.OpenText(); 
            String originalPath = file.FullName; 
            string input = streamreader.ReadToEnd(); 
            Console.WriteLine("input : {0}", input); 
            String tempString = input.Replace(extractedMethod, modifiedMethod); 
            Console.WriteLine("replaced String {0}", tempString); 
            try 
            { 
                sw.Write(tempString); 
                sw.Flush(); 
                sw.Close(); 
                sw.Dispose(); 
                fs.Close(); 
                fs.Dispose(); 
                streamreader.Close(); 
                streamreader.Dispose(); 
                File.Copy(originalPath, originalPath + ".old", true); 
                FileInfo newFile = new FileInfo(originalPath + ".tmp"); 
                File.Delete(originalPath); 
                File.Copy(originalPath + ".tmp", originalPath, true); 
                result = true; 
            } 
            catch (Exception ex) 
            { 
                Console.WriteLine(ex); 
            } 
            return result; 
        }
    }
}


C:\testarea>ConsoleApplication1.exe file.txt padding testing
input :         <style type="text/css">
        <!--
         #mytable {
          border-collapse: collapse;
          width: 300px;
         }
         #mytable th,
         #mytable td
         {
          border: 1px solid #000;
          padding: 3px;
         }
         #mytable tr.highlight {
          background-color: #eee;
         }
        //-->
        </style>
replaced String         <style type="text/css">
        <!--
         #mytable {
          border-collapse: collapse;
          width: 300px;
         }
         #mytable th,
         #mytable td
         {
          border: 1px solid #000;
          testing: 3px;
         }
         #mytable tr.highlight {
          background-color: #eee;
         }
        //-->
        </style>
4
Robert Harvey

Après avoir rencontré cette erreur et ne rien trouvé sur le Web qui me règle, j'ai pensé ajouter une autre raison pour obtenir cette exception, à savoir que les chemins source et cible de la commande Copie de fichier sont les mêmes. Il m'a fallu un certain temps pour le comprendre, mais il peut être utile d'ajouter du code quelque part pour générer une exception si les chemins source et de destination pointent vers le même fichier.

Bonne chance!

4
Alan

Exécutez-vous un analyseur antivirus en temps réel par hasard? Si c'est le cas, vous pouvez essayer de le désactiver (temporairement) pour voir si c'est l'accès au fichier que vous essayez de supprimer. (La suggestion de Chris d'utiliser le processus Sysinternals Explorer est bonne). 

3
Moe Sisko

Essayez ceci: cela fonctionne dans tous les cas, si le fichier n'existe pas, il le créera puis l'écrira. Et s'il existe déjà, pas de problème, il s'ouvrira et vous écrira

 using (FileStream fs= new FileStream(@"File.txt",FileMode.Create,FileAccess.ReadWrite))
 { 
   fs.close();
 }
 using (StreamWriter sw = new StreamWriter(@"File.txt")) 
 { 
   sw.WriteLine("bla bla bla"); 
   sw.Close(); 
 } 
3
PureSilence

Après avoir créé un fichier, vous devez forcer le flux à libérer les ressources:

//FSm is stream for creating file on a path//
System.IO.FileStream FS = new System.IO.FileStream(path + fname,
                                                   System.IO.FileMode.Create);
pro.CopyTo(FS);
FS.Dispose();
0
Faisal Arshad