Fichier utilisé par un autre processus après avoir utilisé File.Create ()

118

J'essaie de détecter si un fichier existe au moment de l'exécution, sinon, créez-le. Cependant, j'obtiens cette erreur lorsque j'essaye d'y écrire:

Le processus ne peut pas accéder au fichier «myfile.ext» car il est utilisé par un autre processus.

string filePath = string.Format(@"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre); 
if (!File.Exists(filePath)) 
{ 
    File.Create(filePath); 
} 

using (StreamWriter sw = File.AppendText(filePath)) 
{ 
    //write my text 
}

Des idées pour y remédier?

Brett
la source

Réponses:

112

La File.Createméthode crée le fichier et ouvre un FileStreamsur le fichier. Votre fichier est donc déjà ouvert. Vous n'avez pas vraiment besoin de la méthode file.Create:

string filePath = @"c:\somefilename.txt";
using (StreamWriter sw = new StreamWriter(filePath, true))
{
    //write to the file
}

Le booléen dans le StreamWriterconstructeur entraînera l'ajout du contenu si le fichier existe.

Chris Dunaway
la source
J'ai essayé le code ci-dessus mais j'obtiens la même erreur lorsque le fichier est créé et lorsqu'il essaie d'écrire dans le fichier, il montre que le fichier est utilisé par un autre processus.
Anmol Rathod
@AnmolRathod assurez-vous que vous n'utilisez pas de File.Create()méthode! L'extrait ci-dessus crée déjà le fichier!
Daniel Eisenreich
138
    File.Create(FilePath).Close();
    File.WriteAllText(FileText);

Je veux mettre à jour cette réponse pour dire que ce n'est pas vraiment le moyen le plus efficace d'écrire tout le texte. Vous ne devriez utiliser ce code que si vous avez besoin de quelque chose de rapide et de sale.

J'étais un jeune programmeur quand j'ai répondu à cette question, et à l'époque, je pensais que j'étais une sorte de génie pour trouver cette réponse.

Carsen Daniel Yates
la source
4
J'adore le fait que toutes les autres réponses étaient trop compliquées. Les gens ne se rendent pas compte qu'il existe une réponse plus simple à chaque problème.
Carsen Daniel Yates
14
L'inconvénient de ce code est qu'il ouvre inutilement le fichier deux fois. De plus, il n'est pas vraiment nécessaire de vérifier si le fichier existe, car le constructeur FileStream le créera automatiquement pour vous s'il n'existe pas, à moins que vous ne lui disiez explicitement de ne pas le faire.
reirab
2
@reirab C'est tout à fait relatif. J'ai besoin de vérifier si le fichier existe et si c'est le cas, supprimez-le et créez-le à nouveau, donc cette réponse est préférée dans mon cas.
makoshichi
1
@SO Alors vous avez un problème différent de l'OP, juste un problème lié. De plus, dans votre cas, vous pouvez toujours simplement utiliser le FileStream(string, FileMode)constructeur et lui transmettre FileMode.Create , qui écrasera tout fichier existant. Toujours pas besoin d'ouvrir le fichier deux fois. De plus, cette réponse a été modifiée après la publication de mon commentaire original.
reirab
2
Le point de cette réponse est de montrer que vous pouvez simplement ajouter .Close()à la fin, donc cela fonctionne dans tous les cas. Je me méfie du système d'utilisation FileStreampour tout parce que je ne veux pas que l'exception se produise sur le fait FileMode.Createque le fichier est déjà là - en particulier lorsque je veux effacer le contenu et ne pas y ajouter FileMode.Open. Pour moi, cela FileStreamne fonctionne vraiment qu'après avoir supprimé le fichier en question, puis écrit dessus. Puisqu'il le File.Createlaisse ouvert et verrouillé, il semble que .Close()cela soit le seul véritable moyen de gérer mon scénario et les SO.
vapcguy
25

Lors de la création d'un fichier texte, vous pouvez utiliser le code suivant:

System.IO.File.WriteAllText("c:\test.txt", "all of your content here");

En utilisant le code de votre commentaire. Le fichier (flux) que vous avez créé doit être fermé. File.Create renvoie le flux de fichiers au fichier qui vient d'être créé:

string filePath = "filepath here";
if (!System.IO.File.Exists(filePath))
{
    System.IO.FileStream f = System.IO.File.Create(filePath);
    f.Close();
}
using (System.IO.StreamWriter sw = System.IO.File.AppendText(filePath))
{ 
    //write my text 
}
Ralf de Kleine
la source
Je ne semble pas avoir d'option de fermeture. Voici le code: string filePath = string.Format (@ "{0} \ M {1} .dat", ConfigurationManager.AppSettings ["DirectoryPath"], costCentre); if (! File.Exists (filePath)) {File.Create (filePath); } en utilisant (StreamWriter sw = File.AppendText (filePath)) {// écrire mon texte}
Brett
File.Createrevient FileStreamet qui aClose()
Null Head
15
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();
utilisateur3430377
la source
7
Bienvenue dans Stackoverflow. Vous devriez au moins rédiger une brève description pour décrire votre réponse / solution.
Paresh Mayani
9

File.Create renvoie un FileStream. Vous devez le fermer lorsque vous avez écrit dans le fichier:

using (FileStream fs = File.Create(path, 1024)) 
        {
            Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
            // Add some information to the file.
            fs.Write(info, 0, info.Length);
        }

Vous pouvez utiliser using pour fermer automatiquement le fichier.

Kimtiede
la source
Bien que l'OP essaie d'ouvrir un StreamWritercomme cela peut être déduit de son utilisation de File.AppendText.
binki
8

J'ai mis à jour votre question avec l'extrait de code. Après une mise en retrait correcte, le problème est immédiatement clair: vous utilisez File.Create()mais ne fermez pas le FileStreamqu'il renvoie.

Faire de cette façon est inutile, StreamWriterpermet déjà d'ajouter à un fichier existant et de créer un nouveau fichier s'il n'existe pas encore. Comme ça:

  string filePath = string.Format(@"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre); 
  using (StreamWriter sw = new StreamWriter(filePath, true)) {
    //write my text 
  }

Qui utilise ce StreamWriterconstructeur .

Hans Passant
la source
1

Cette question a déjà reçu une réponse, mais voici une solution du monde réel qui vérifie si le répertoire existe et ajoute un numéro à la fin si le fichier texte existe. J'utilise ceci pour créer des fichiers journaux quotidiens sur un service Windows que j'ai écrit. J'espère que ça aidera quelqu'un.

// How to create a log file with a sortable date and add numbering to it if it already exists.
public void CreateLogFile()
{
    // filePath usually comes from the App.config file. I've written the value explicitly here for demo purposes.
    var filePath = "C:\\Logs";

    // Append a backslash if one is not present at the end of the file path.
    if (!filePath.EndsWith("\\"))
    {
        filePath += "\\";
    }

    // Create the path if it doesn't exist.
    if (!Directory.Exists(filePath))
    {
        Directory.CreateDirectory(filePath);
    }

    // Create the file name with a calendar sortable date on the end.
    var now = DateTime.Now;
    filePath += string.Format("Daily Log [{0}-{1}-{2}].txt", now.Year, now.Month, now.Day);

    // Check if the file that is about to be created already exists. If so, append a number to the end.
    if (File.Exists(filePath))
    {
        var counter = 1;
        filePath = filePath.Replace(".txt", " (" + counter + ").txt");
        while (File.Exists(filePath))
        {
            filePath = filePath.Replace("(" + counter + ").txt", "(" + (counter + 1) + ").txt");
            counter++;
        }
    }

    // Note that after the file is created, the file stream is still open. It needs to be closed
    // once it is created if other methods need to access it.
    using (var file = File.Create(filePath))
    {
        file.Close();
    }
}
Alcyon
la source
1

Je sais que c'est une vieille question, mais je veux juste jeter ceci là-bas que vous pouvez toujours utiliser File.Create("filename")", ajoutez-y simplement .Dispose().

File.Create("filename").Dispose();

De cette façon, il crée et ferme le fichier pour que le processus suivant l'utilise.

Je suis Batman
la source
1
File.Create(FilePath).Close();de la réponse ci-dessus a this.Dispose(true); GC.SuppressFinalize((object) this);dans sa mise en œuvre.
Ghukas
1

Je pense connaître la raison de cette exception. Vous exécutez peut-être cet extrait de code dans plusieurs threads.

Kusala Subasinghe
la source
Pour moi, c'était le problème que j'écrive un fichier journal de manière asyncron (dans un thread différent: Task.Run () sans attendre (exprès), et cela provoque un accès multithread au même fichier.
Bence Végert
-1

Essayez ceci: cela fonctionne dans tous les cas, si le fichier n'existe pas, il le créera et y écrira. Et s'il existe déjà, aucun problème il s'ouvrira et y é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(); 
 } 
PureSilence
la source
1
en utilisant fermera le fichier en appelant Dispose. Dans votre exemple de fichier a été fermé deux fois
Valentine Zakharenko